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

  • 相关阅读:
    HDU 2089 不要62
    HDU 5038 Grade(分级)
    FZU 2105 Digits Count(位数计算)
    FZU 2218 Simple String Problem(简单字符串问题)
    FZU 2221 RunningMan(跑男)
    FZU 2216 The Longest Straight(最长直道)
    FZU 2212 Super Mobile Charger(超级充电宝)
    FZU 2219 StarCraft(星际争霸)
    FZU 2213 Common Tangents(公切线)
    FZU 2215 Simple Polynomial Problem(简单多项式问题)
  • 原文地址:https://www.cnblogs.com/techyc/p/3349294.html
Copyright © 2011-2022 走看看