当前位置: 首页 > 工具软件 > QuickFIX/J > 使用案例 >

QuickFIX/J常见问题汇总

姜锋
2023-12-01

最近在搞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

 

 

转载于:https://www.cnblogs.com/techyc/p/3349294.html

 类似资料: