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

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM