zoukankan      html  css  js  c++  java
  • QuickFIX/J常见问题汇总

    最近在搞QuickFIX/J,网上的资料不算很多,遇到一些简单的问题都需要google一阵才能找到解决方法,因此做点记录:

    错误:Rejecting invalid message: quickfix.UnsupportedMessageType

    这个异常的产生,有两个条件:

    1) UseDataDictionary = N

    2) 没有覆盖对应的onMessage方法

    具体说来,如果没有将UseDataDictionary设为N,几时没有覆盖对应的onMessage方法,也不会产生这个异常。

    至于没有覆盖对应的onMessage方法,是指覆盖的onMessage方法,参数必须是接收的信息的类型:

        //Will throws error
        @Override
        public void onMessage(Message message, SessionID sessionID)
            throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue{
          super.onMessage(message, sessionID);
          System.out.println("--crack--");
        }
        
        //Correct!
        @Override
        public void onMessage(ExecutionReport message, SessionID sessionID)
            throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue {
          System.out.println("--crack ER--");
        }

    如果接收的信息35=8(ExecutionReport),则需用第二个onMessage方法,而非第一个。

    在FIX信息中,自定义域(Add new field)

    在QuickFIX/J中新增自定义域,最简单的就是修改对应版本的xml文件,在xml文件里增加自定义域,然后在配置文件中设置如下:

    UseDataDictionary=Y
    DataDictionary=config/FIX42.xml

    用这种方法去指定自定义的DataDictionary文件。

    但此方法有两个缺点:

    1) 接收信息,解析自定义域数据时,只能使用类型不安全的解析

    @Override
    public void onMessage(ExecutionReport message, SessionID sessionID)
            throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue {
        System.out.println("--crack ER--");
        StringField field = new StringField(10041);
        System.out.println(message.getField(field).toString());
    }

    假设新增了10041这个域(FIX Tag),由于QuickFIX/J包里默认没有这个域对应的对象,这能使用这种方法取得这个域的值,而这种方法在官方文档里描述为类型不安全,并不推荐。

    2) 当自定义域的信息含有Repeating Group时,会抛出Out of order repeating group members这个错误。暂时还未找到解决方法

    最好的解决方法,是修改xml文件,新增自定义域(Field)和消息类型(Message Type)后,重新build一个自定义的.jar文件。

    使用这种方法需要注意的是,如果自定义域和自定义消息类型只针对某一个版本的FIX,例如只修改了FIX42.xml,而QuickFIX/J默认是将所有的Field放在“quickfix.field”这个包里,并非如消息类型那样分开不同版本的包放,因此自定义的Field有可能会被其它版本(如FIX43/44)覆盖。

    看来这个类quickfix.codegen.MessageCodeGenerator.java:

    public static void main(String[] args) {
            MessageCodeGenerator codeGenerator = new MessageCodeGenerator();
            try {
                if (args.length != 3) {
                    String classname = MessageCodeGenerator.class.getName();
                    System.err.println("usage: " + classname + " specDir xformDir outputBaseDir");
                    return;
                }
    
                boolean overwrite = getOption(OVERWRITE_OPTION, true);
                boolean orderedFields = getOption(ORDERED_FIELDS_OPTION, false);
                boolean useDecimal = getOption(BIGDECIMAL_TYPE_OPTION, false);
    
                long start = System.currentTimeMillis();
    //            final String[] vers = new String[] { "FIXT 1.1", "FIX 5.0", "FIX 4.4", "FIX 4.3", "FIX 4.2",
    //                    "FIX 4.1", "FIX 4.0" };
                final String[] vers = new String[] {"FIXT 1.1","FIX 4.2"};
                for (int i = 0; i < vers.length; ++i) {
                    Task task = new Task();
                    task.setName(vers[i]);
                    final String temp = stripSpaces(vers[i]);
                    task.setSpecification(args[0] + "/" + temp + ".xml");
                    task.setTransformDirectory(args[1]);
                    task.setMessagePackage("quickfix." + temp.toLowerCase());
                    task.setOutputBaseDirectory(args[2]);
                    task.setFieldPackage("quickfix.field");
                    task.setOverwrite(overwrite);
                    task.setOrderedFields(orderedFields);
                    task.setDecimalGenerated(useDecimal);
                    codeGenerator.generate(task);
                }
                double duration = System.currentTimeMillis() - start;
                DecimalFormat durationFormat = new DecimalFormat("#.###");
                codeGenerator.log.info("Time for generation: "
                        + durationFormat.format(duration / 1000L) + " seconds");
            } catch (Exception e) {
                codeGenerator.log.error("error during code generation", e);
                System.exit(1);
            }
    }

    留意注释部分是默认的实现。可以看到setMessagePackage和setFieldPackage之间的不同。

    成功build了以后,就可以这样解析10041(name=BoInstrumentCode2)这个自定义域:

    public void onMessage(quickfix.fix42.ExecutionReport message,
                SessionID sessionID) throws FieldNotFound {
            
            System.out.println(message.getBoInstrumentCode2().toString());
    }

    简单清晰,面向对象

    参考:

    http://www.quickfixj.org/confluence/display/qfj/User+FAQ

    http://www.quickfixj.org/quickfixj/usermanual/1.5.3/usage/configuration.html#Sample Settings File

  • 相关阅读:
    flask_admin+flask_login 整合,jieba分词+echarts数据分析可视化
    古诗词网爬虫实现
    Flask admin Flask login 整合模板
    API网关Kong
    Flask添加新命令
    MyBatis连接MySQL8配置
    golang锁
    golang goroutine
    golang管道
    golang结构体
  • 原文地址:https://www.cnblogs.com/techyc/p/3349294.html
Copyright © 2011-2022 走看看