FIX協議是由國際FIX協會組織提供的一個開放式協議,目的是推進國際貿易電子化的進程,在各種參與者之間,包括投資經理、經紀人,買方、賣方創建起實時的電子化通信協議。FIX協議的目標是把各種證券金融業務需求流程格式化,使之成爲一個個可用計算機語言描述的功能流程,並在每一個業務功能接口上統一交換格式,方便各個功能模塊的鏈接。java
通訊模型git
Initiator :發起者,創建通訊連路,經過發送初始Logon消息發起會話的參與方。github
Acceptor :接收方 FIX會話的接收方。負責執行第一層次的認證和經過傳輸Logon消息的確認正式聲明鏈接請求被接受。算法
原則:先發起者爲Initiator ,接受者爲Acceptor 。數組
標準模式以網關爲Acceptor,客戶端爲Initiator作爲經常使用模式。安全
Fix connection服務器
FIX鏈接 由3部分組成:logon登陸,message exchange消息傳輸,logout註銷。網絡
Fix sessionsession
FIX會話由一個或多個FIX Connection FIX鏈接組成。一個FIX會話能夠有屢次登陸。app
序列號
全部的FIX消息都由一個惟一的序列號進行標示。序列號在每個FIX會話開始時被初始化爲1,並在整個會話期間遞增。監控序列號可使會話參與者識別和處理丟失的消息,當在一個FIX會話中從新鏈接時可以快速進行應用程序同步。
每一個會話將創建一組互不依賴的接受和發送序列。會話參與者將維護一個賦予發送消息的序列和一個監控接受消息的消息塊間隙序列號。
心跳
在消息交互期間,FIX應用程序將週期性產生Heartbeat心跳消息。該心跳消息能夠監控通訊鏈路狀態及識別接收序列號間隙。發送Heartbeat的週期間隔由會話發起者使用在Logon消息中HeartBtInt域進行定義。
Heartbeat心跳消息的時間間隔應當在每個消息發送後復位,即發送一個消息後,在間隔給定的時間內無其它消息發送則發送一個Heartbeat心跳消息。HeartBtInt的值應當被會話雙方認同,由會話發起方定義並由會話接收者經過Logon消息進行確認。同一個HeartBtInt被會話雙方——登陸的發起者和登陸的接受者共同使用。
數據完整校驗
消息數據內容的完整性能夠參用兩種方式來驗證:消息長度和效驗碼檢查。
程序經過計算BodyLength域到CheckSum標記(「10=」)分界符的字符數,域BodyLength標示的消息長度進行比較來完成完整性效驗。
ChekSum完整性檢查,經過計算從域「8=」 中「8」開始,包括緊跟在CheckSum標記域的分界符每一個字符的2進制和同CheckSum進行比較獲得。
一個FIX消息校驗和經過計算到ChechSum域(但不包括)的消息的每一個字節和獲得。而後,校驗和被轉換爲模256的數字用於傳送和比較。校驗和在全部加密操做以後被計算。
校驗代碼:
樣例:8=FIX.4.29=7335=A34=149=CLIENT52=20181119-10:42:48.76856=SERVER98=0108=30141=Y10=208 1、消息長度:9=73 35=A34=149=CLIENT52=20181119-10:42:48.76856=SERVER98=0108=30141=Y(這段長度) 2、效驗碼檢查 char *GenerateCheckSum( char *buf, long bufLen ) { static char tmpBuf[ 4 ]; long idx; unsigned int cks; for( idx = 0L, cks = 0; idx < bufLen; cks += (unsigned int)buf[ idx++ ] ); sprintf( tmpBuf, 「%03d」, (unsigned int)( cks % 256 ) ); return( tmpBuf ); }
消息確認
FIX協議不支持單個消息的確認。採用的是監控消息時隙的方法來進行消息恢復和驗證。
普通的數據傳送(無單個消息確認)經過消息序列間隙進行錯誤識別。每一個消息由一個惟一的序列號進行標示。接收端應用程序負責監控接收消息序列號以識別消息間隙併產生重傳請求。
每一個FIX參與方必須爲FIX會話維護兩個序列號,一個是接收序列號,一個是發送序列號,二者都在創建FIX會話開始時初始化爲1。每一個消息被賦予一個惟一的序列號值,並在消息發送後遞增。此外,每一個收到的消息都有一個惟一的序列號,接收序列號計數器在收到每一個消息後將會被遞增。
當接收序列號與所但願獲得的的正確序列號沒必要配時,必須採起糾錯處理。
加密
加密算法由鏈接雙方共同協商。
一個消息的任何一個域能夠被加密並放在SecureData域中。然而,一些顯示的標誌域必須採用明文進行傳輸。爲確保完整性,明文域能夠在SecureData域中重複。
當使用加密時,建議但不是必須,全部的消息體都進行加密。若是一個消息中的重複組數據中的部分數據要加密,這個重複組必須所有進行加密。
預先協商好的加密算法在Logon消息中進行聲明。
自定義域
FIX爲給用戶提供最大的靈活性,FIX協議容許用戶自定義域。這些域在認同的參與者之間實現、應用,而且應注意避免衝突。
Tag數在5000 到9999保留用於用戶自定義域。這些tag值用於企業聯盟的信息交換。能夠經過FIX網站進行註冊。
10000以上保留用於單一企業內部使用。不用註冊。
整數int,浮點數float,單個字符char,布爾Boolean,字符串String,數據data
常見域
Tag(標記) | FieldName(域名) | 備註 |
---|---|---|
8 | BeginString | 起始串,FIX協議版本 |
9 | BodyLength | 消息長度 |
35 | MsgType | 消息類型:例如F=Order Cancel Request,取消訂單 |
11 | ClOrdID | 客戶端訂單ID |
37 | OrderID | 服務端訂單ID |
41 | OrigClOrdID | 原始客戶端訂單ID |
54 | Side | 買賣類型。例如:1 = Buy,2 = Sell |
55 | Symbol | 股票代碼。例如:YRD |
10 | CheckSum | 校驗碼 |
域語法
開始部分應是消息頭,隨後是正文,最後是消息尾;
消息頭的前 3 個域的次序不能改變:起始串(Tag =8)、消息體長度(Tag =9)、消息類型(Tag =35);
消息尾的最後一個域應是校驗和域(Tag=10);
重複組中,域出現的順序應遵循該重複組在消息或組件中定義時的次序;
在一條消息中,除重複組域外任何其餘域不能重複出現。
安全與加密
因爲消息有可能在公網或不安全的網絡上傳輸交換,所以須要對相關的敏感數據加密處理。
具體加密的方法由鏈接雙方達成的協議而定。
消息內除某些須要公開識別的域以明文傳輸外其餘任何域均可以加密放置密文數據域 (SecureData)內。固然,這些被加密的域也能夠同時保留明文的表示方式。
當決定使用加密方案時,能夠對消息正文內全部的域加密。若是消息的重複組內有部分須要加密的,那麼要求對整個重複組加密。
本協議還提供的一些域用以支持數字簽名、密鑰交換和正文加密等安全技術。
消息頭
每個會話或應用消息有一個消息頭,該消息頭指明消息類型、消息體長度、發送目的地、消息序號、發送起始點和發送時間。
Tag | 域名 | 必需 | 說明 |
---|---|---|---|
8 | BeginString | Y | 起始串,取值:FIX.4.2(不可加密,消息的第一個域) |
9 | BodyLength | Y | 消息體長度(不可加密,消息的第二個域) |
35 | MsgType | Y | 消息類型(不可加密,消息的第三個域) |
49 | SenderCompID | Y | 發送方代碼(不可加密,發送方標識符) |
59 | TargetCompID | Y | 接收方代碼(不可加密,接收方標識符) |
115 | OnBehalfOfCompID | N | 最初發送方標識符(可加密),用於經第三方發送。 |
128 | DeliverToCompID | N | 最終接收方標識符(可加密),用於經第三方發送。 |
90 | SecureDataLen | N | 密文數據長度 |
91 | SecureData | N | 密文數據(緊跟密文數據長度域) |
34 | MsgSeqNum | Y | 消息序號(可加密),若是交易雙方不採用 FIX 會話 機制,可將該 tag 置爲一個固定的值,例如 0。 |
50 | SenderSubID | N | 發送方子標識符(可加密) |
142 | SenderLocationID | N | 發送方方位標識符(可加密) |
57 | TargetSubID | N | 接收方子標識符(可加密) |
143 | TargetLocationID | N | 接收方方位標識符(可加密) |
116 | OnBehalfOfSubID | N | 最初發送方子標識符(可加密) |
144 | OnBehalfOfLocationID | N | 最初發送方方位標識符(可加密) |
129 | DeliverToSubID | N | 最終接收方子標識符(可加密) |
145 | DeliverToLocationID | N | 最終接收方方位標識符(可加密) |
43 | PossDupFlag | N | 可能重複標誌,重複發送時,做此標記。(可加密) |
97 | PossResend | N | 可能重發標誌。(可加密) |
52 | SendingTime | Y | 發送時間(可加密) |
122 | OrigSendingTime | N | 原始發送時間(可加密) |
347 | MessageEncoding | N | 消息中 Encoded 域的字符編碼類型(非 ASCII 碼) |
369 | LastMsgSeqNumProcesse d | N | 最後處理消息序號(可加密) |
370 | OnBehalfOfSendingTime | N | 最初發送時間(用 UTC 表示時間) |
消息尾
每個消息(會話或應用消息)有一個消息尾,並以此終止。消息尾可用於分隔多個消息,包含有 3 位數的校驗和值。
Tag | 域名 | 必需 | 說明 |
---|---|---|---|
93 | SignatureLength | N | 數字簽名長度(不可加密) |
89 | Signature | N | 數字簽名(不可加密) |
10 | CheckSum | Y | 校驗和,消息的最末域。(不可加密) |
新訂單消息(MsgType=D)
對於在消息頭中設置了 PossResend 標誌的訂單消息,應當使用交易客戶方訂單編號(ClOrdID)核 實是否已收到該訂單,具體實現時還應檢查訂單參數(買賣方向、證券代碼、數量等)進行覈實。若是 以前收到該訂單,應以執行報告消息迴應訂單狀態。若是以前未收到,則以執行報告消息迴應訂單確認。
Tag | 域名 | 必需 | 說明 |
---|---|---|---|
標準消息頭 | Y | MsgType=D | |
11 | ClOrdID | Y | 交易客戶方訂單編號,在訂單有效交易日內必需 |
109 | ClientID | Y | 客戶資金賬號 |
1 | Account | Y | 客戶交易編碼 |
110 | MinQty | N | 最小成交量。 |
55 | Symbol | Y | 期貨合約代碼 |
167 | SecurityType | N | FUT = 期貨 |
200 | MaturityMonthYear | N | 用於指按期貨到期的年和月 |
205 | MaturityDay | N | 用於期貨的到期日期,並被與到期年月(MaturityMonthYear)聯合使用 |
207 | SecurityExchange | Y | 用於指定交易所 |
77 | OpenClose | Y | 指明開倉,平倉 |
8009 | HedgeFlag | Y | 投機套保標誌 |
8010 | TouchCondition | N | 觸發條件 |
54 | Side | Y | 買賣方向 |
38 | OrderQty | N | 委託手數 |
60 | TransactTime | Y | 訂單發起時間 |
40 | OrdType | Y | 訂單類型 |
44 | Price | N | 價格(限價訂單時有效) |
423 | PriceType | N | 價格類型 |
99 | StopPx | N | 中止價 |
15 | Currency | N | 幣種 |
59 | TimeInForce | N | 新訂單生效時間,默認爲當日有效 |
168 | EffectiveTime | N | 用於指定定單有效的時間 |
432 | ExpireDate | N | 有條件地用於在生效時間(TimeInForce)=在某 日前有效(GTD),而沒有指定截止時間 (ExpireTime)的狀況之下 |
126 | ExpireTime | N | 有條件地用於生效時間(TimeInForce) = 在某 日前有效(GTD)和到期日沒有被指定的狀況之 下 |
8096 | MacNetInfo | N | 委託方的機器網絡信息 |
標準消息尾 | Y |
執行報告消息(MsgType=8)
訂單確認
訂單狀態變化確認(如撤單確認)
發送訂單的成交回報
訂單拒絕
Tag | 域名 | 必需 | 說明 |
---|---|---|---|
標準消息頭 | Y | MsgType=8 | |
37 | OrderID | Y | 期貨公司委託號,同個交易日必需保證惟一 |
11 | ClOrdID | N | 交易客戶方訂單編號。若是是強平回報,則該值 取值爲以」NONE」開頭的當天交易日惟一的字符 串標識 |
42 | OrigClOrdID | N | 原始交易客戶方訂單編號,指示被撤消訂單的 ClOrdID |
17 | ExecID | Y | 期貨公司的執行編號,在訂單有效交易日內應保證惟一 |
150 | ExecType | Y | 執行類型 |
39 | OrdStatus | Y | 訂單狀態 |
103 | OrdRejReason | N | 訂單拒絕時須要 |
109 | ClientID | Y | 客戶資金賬號 |
1 | Account | Y | 客戶交易編碼 |
55 | Symbol | Y | 期貨合約代碼 |
167 | SecurityType | N | FUT=期貨 |
200 | MaturityMonthYear | N | 到期年月 |
205 | MaturityDay | N | 到期日期 |
207 | SecurityExchange | Y | 用於指定交易所 |
77 | OpenClose | N | 指明開倉,平倉 |
54 | Side | Y | 買賣方向 |
38 | OrderQty | Y | 委託手數 |
40 | OrdType | N | 訂單類型 |
44 | Price | N | 訂單價格 |
99 | StopPx | N | 中止價 |
59 | TimeInForce | N | 新訂單生效時間,默認爲當日有效 |
15 | Currency | N | 幣種 |
32 | LastShares | N | 上一成交數(最近一筆成交數量) |
31 | LastPx | N | 上一成交價(最近一筆成交價格) |
30 | LastMkt | N | 上一成交市場 |
151 | LeavesQty | Y | 訂單剩餘數量 |
14 | CumQty | Y | 成交總數 |
6 | AvgPx | Y | 成交平均價 |
60 | TransactTime | N | 執行報告時間 |
381 | GrossTradeAmt | N | 成交總金額 |
110 | MinQty | N | 最小成交量 |
8500 | OrderEntryTime | N | 訂單申報時間 |
8093 | DeclarationID | N | 報單號 |
8094 | TradeID | N | 撮合編號 |
標準消息尾 | Y |
訂單狀態請求消息(MsgType=H)
訂單狀態請求用於向交易服務方請求某訂單的狀態,交易服務方經過執行報告消息返回訂單狀態。
Tag | 域名 | 必需 | 說明 |
---|---|---|---|
標準消息頭 | Y | MsgType=H | |
37 | OrderID | Y | 期貨公司委託號,同個交易日必需保證惟一 |
11 | ClOrdID | Y | 交易客戶方訂單編號 |
109 | ClientID | Y | 客戶資金賬號 |
1 | Account | Y | 客戶交易編碼 |
55 | Symbol | Y | 期貨合約代碼 |
207 | SecurityExchange | Y | 用於指定交易所 |
167 | SecurityType | N | FUT=期貨 |
200 | MaturityMonthYear | N | 用於指按期貨到期的年和月 |
205 | MaturityDay | N | 用於期貨的到期日期,並被與到期年月(MaturityMonthYear)聯合使用 |
54 | Side | Y | 買賣方向 |
標準消息尾 | Y |
撤單消息(MsgType=F)
撤單消息用以撤消訂單的所有訂單剩餘數量。
撤單消息也被賦予一個 ClOrdID,可視做另一個訂單。若是被拒絕,撤單拒絕消息的 ClOrdID 放 置撤單消息的 ClOrdID,而原始訂單的 ClOrdID 則放入 OrigClOrdID 域。ClOrdID 要保證惟一。
Tag | 域名 | 必需 | 說明 |
---|---|---|---|
標準消息頭 | Y | MsgType=F | |
41 | OrigClOrdID | Y | 原始交易客戶方訂單編號,指示被撤消訂單的ClOrdID |
37 | OrderID | Y | 期貨公司委託號,同個交易日必需保證惟一 |
11 | ClOrdID | Y | 交易客戶方訂單編號 |
109 | ClientID | Y | 客戶資金賬號 |
1 | Account | Y | 客戶交易編碼 |
55 | Symbol | Y | 期貨合約代碼 |
167 | SecurityType | N | 證券代碼源 |
200 | MaturityMonthYear | N | FUT=期貨 |
205 | MaturityDay | N | 期貨到期年月 |
207 | SecurityExchange | Y | 期貨到期日期 |
54 | Side | Y | 買賣方向 |
60 | TransactTime | Y | 訂單發起時間 |
40 | OrdType | Y | 訂單類型 |
38 | OrderQty | Y | 委託手數 |
8093 | DeclarationID | N | 報單號 |
58 | Text | N | |
標準消息尾 | Y |
撤單拒絕消息(MsgType=9)
本消息用於撤單消息的拒絕。
交易服務方接收到撤單發現沒法執行(已成交訂單不可更改等),將發送撤單拒絕。
拒絕撤單時,撤單拒絕消息應用 ClOrdID 指示撤單的 ClOrdID,用 OrigClOrdID 指示以前最後接受的訂單(除非拒絕緣由是「未知訂單」)。
Tag | 域名 | 必需 | 說明 |
---|---|---|---|
標準消息頭 | Y | MsgType=9 | |
37 | OrderID | Y | 期貨公司委託號,同個交易日必需保證惟一 |
11 | ClOrdID | Y | 交易客戶方訂單編號 |
41 | OrigClOrdID | Y | 原始交易客戶方訂單編號,指示被撤消訂單的ClOrdID |
39 | OrdStatus | Y | 訂單狀態 |
109 | ClientID | Y | 客戶資金賬號 |
1 | Account | Y | 客戶交易編碼 |
60 | TransactTime | N | 訂單發起時間 |
434 | CxlRejResponseTo | N | 撤單拒絕迴應類型 |
102 | CxlRejReason | N | 撤單拒絕緣由 |
58 | Text | N | |
標準消息尾 | Y |
配置 | 描述 | 有效值 | 默認 |
---|---|---|---|
BeginString | 會話使用的FIX版本號(發送和接收消息起始字符串) | FIXT.1.一、FIX.4.四、FIX.4.三、FIX.4.二、FIX.4.一、FIX.4.0 | |
SenderCompID | 會話當中定義本方的ID | 區分大小寫的字符串 | |
SenderSubID | 會話相關的本方的子ID號 (可選) | 區分大小寫的字符串 | |
SenderLocationID | 會話相關的本方的locationID號 (可選) | 區分大小寫的字符串 | |
TargetCompID | 本會話當中的對方ID | 區分大小寫的字符串 | |
TargetSubID | 本會話當中的對方SubID (可選) | 區分大小寫的字符串 | |
TargetLocationID | 本會話當中的對方locationID (可選) | 區分大小寫的字符串 | |
SessionQualifier | 附加的限定詞,用於消除歧義,保證會話的惟一性 | 區分大小寫的字符串 | |
DefaultApplVerID | 僅FIXT1.1(或以上版本)須要。忽略早期版本的傳輸。指定會話的默認應用程序的版本ID。ApplVerID的枚舉值(請看ApplVerID字段詳細介紹),或默認BeginString。 | FIX.5.0SP二、FIX.5.0SP一、FIX.5.0、FIX.4.四、FIX.4.三、FIX.4.二、FIX.4.一、FIX.4.0 | |
ConnectionType | 定義會話當中本方的角色:acceptor或者initiator | initiator、acceptor | |
StartTime | 交易日的會話有效開始時間,這時FIX會話被激活 | UTC時間,格式: HH:MM:SS | |
EndTime | 交易日的會話失效時間,FIX會話將被中止 | UTC時間,格式: HH:MM:SS | |
StartDay | 對於爲期一週的會話配置,一週會話開始的第一天。與STARTTIME結合使用。 | 使用一週中某天的英語任何縮寫都是有效的(好比,mo, mon, mond, monda,Monday都是有效的) | |
EndDay | 對於爲期一週的會話配置,一週會話結束的最後一天。與EndTime結合使用。 | 使用一週中某天的英語任何縮寫都是有效的(好比,mo, mon, mond, monda,Monday都是有效的) | |
MillisecondsInTimeStamp | 時間戳是否加入毫秒。FIX.4.2和更高版本可用。 | Y、N | Y |
ResetOnLogon | 接收登陸請求時,序列號是否要復位。只用於Acceptor | Y、N | N |
ResetOnLogout | 正常註銷登陸時,序列號是否要復位 | Y、N | N |
ResetOnDisconnect | 鏈接異常斷開後是否要將序列號重置爲1 | Y、N | N |
RefreshOnLogon | 肯定是否應當從持久層登陸時恢復會話狀態。在建立熱故障切換會話時有用。 | Y、N | N |
EnableLastMsgSeqNumProcessed | 是否在header中添加最後一條消息的序列號(可選tag369)。 | Y、N | N |
MaxMessagesInResendRequest | 設置一次重發請求的消息的最大消息數。 | 任何大於0的整數。使用0爲無窮大(默認)。 | 0 |
SendLogoutBeforeDisconnectFromTimeout | 指定是否因超時斷開鏈接以前發送logout消息 | Y、N | N |
IgnorePossDupResendRequests | 當PossDupFlag(tag 43)設置爲true時,是否忽略一次重發請求 | Y、N | N |
配置 | 描述 | 有效值 | 默認 |
---|---|---|---|
UseDataDictionary | 告訴會話是否使用數據字典,或不但願使用數據字典。 若是你要使用repeating group,你必須使用DataDictionary。 | Y、N | Y |
DataDictionary | 該配置只用於比FIXT.1.1還老的版本。詳細參考FIXT.1.1的TransportDataDictionary和AppDataDictionary的配置。 | FIX44.xml、FIX43.xml、FIX42.xml、FIX41.xml、FIX40.xml | |
TransportDataDictionary | XML定義文件用於驗證傳入的管理消息。若是沒有提供DataDictionary,只會作基本消息的驗證。該配置只用於FIXT.1.1(或更高版本)的會話。 | FIXT1.1.xml | |
AppDataDictionary | 用於驗證應用層消息的XML定義文件。僅對FIXT.1.1(或更高版本)的會話有效。更多信息請參考(FIX.4.0到 FIX.4.4)的DataDictionary。該配置能夠爲每一個會話指定一個自定義應用的數據字典。該配置僅用於FIXT.1.1或更新的傳輸協議。使用FIXT傳輸時,該配置能夠做爲指定多個應用的數據字典的前綴。例如: DefaultApplVerID=FIX.4.2 # For default application version ID AppDataDictionary=FIX42.xml # For nondefault application version ID # Use BeginString suffix for app version AppDataDictionary.FIX.4.4=FIX44.xml | 有效的XML數據字典文件。QuickFIX/N 配備默認的協議字典數據:FIX50SP2.xml、FIX50SP1.xml、FIX50.xml、FIX44.xml、FIX43.xml、FIX42.xml、FIX41.xml、FIX40.xml | |
ValidateFieldsOutOfOrder | 若是設置爲N,字段放置區域錯誤(例如,body字段在header區域內,或在header字段在body區域內)將不會被拒絕。用於鏈接字段要求不嚴格的系統。 | Y、N | Y |
ValidateFieldsHaveValues | 若是設置爲N,沒有值的字段將不會被拒絕。用於鏈接到系統不當發送空標籤。 | Y、N | Y |
ValidateUserDefinedFields | 若是設置爲N,用戶自定義的字段將不會被拒絕,即便沒有在數據字典中定義,或沒出如今消息中。 | Y、N | Y |
配置 | 描述 | 有效值 | 默認 |
---|---|---|---|
ReconnectInterval | 嘗試從新鏈接的時間間隔(秒)。僅用於 initiator。 | 正整數 | 30 |
HeartBtInt | 心跳間隔(秒)。僅用於initiator。 | 正整數 | - |
LogonTimeout | 登陸超時時間間隔(秒) | 正整數 | 10 |
LogoutTimeout | 註銷登陸超時時間間隔(秒) | 正整數 | 2 |
SocketConnectPort | Socket服務端口,用於創建會話。僅用於 initiator | 正整數 | - |
SocketConnectHost | 鏈接主機.僅用於 initiator | x.x.x.x格式IP地址或域名 | - |
SocketConnectPort | 一組備用Socket端口,用於鏈接會話的故障轉移,n是正整數。SocketConnectPort1,SocketConnectPort2 ... 必須是連續的,並有一個與之相匹配的數組SocketConnectHost | 正整數 | - |
SocketConnectHost | 一組備用Socket服務主機,用於鏈接會話的故障轉移,n是正整數。SocketConnectHost1, SocketConnectHost2... 必須是連續的,並有一個與之相匹配的數組SocketConnectPort | x.x.x.x格式IP地址或域名 | - |
SocketNodelay | 鏈接是否禁用Nagle算法。在[DEFAULT]配置節點定義。 | Y、N | Y |
ReconnectInterval | 嘗試從新鏈接的時間間隔(秒)。僅用於 initiator。 | 正整數 | 30 |
配置 | 描述 | 有效值 | 默認 |
---|---|---|---|
SocketAcceptPort | 監聽接入鏈接Socket端口。僅用於acceptor | 正整數,有效的、開放的套接字端口 | - |
SocketAcceptHost | 監聽接入鏈接的Socket服務的主機。若是不提供,acceptor將監聽全部網絡端口(0.0.0.0) | 有效的x.x.x.x格式IP地址 | 0.0.0.0 |
SocketNodelay | 鏈接是否禁用Nagle算法。在[DEFAULT]配置節點定義。 | Y、N | Y |
配置 | 描述 | 有效值 | 默認 |
---|---|---|---|
PersistMessages | 若是設置爲N,被不會保存消息。這樣將迫使quickfix老是發送GapFills,而不是從新發送消息。若是你知道你永遠不須要從新發送消息,使用此配置。有用的市場數據流。 | Y、N | Y |
配置 | 描述 | 有效值 | 默認 |
---|---|---|---|
FileStorePath | 存儲序列號和消息的文件目錄。 | 有效的文件存儲目錄,必須有寫入權限。 | - |
配置 | 描述 | 有效值 | 默認 |
---|---|---|---|
FileLogPath | 存儲日誌的目錄。 | 有效的文件存儲目錄,必須有寫入權限。 | - |
github:QFJ GitHub Repository(https://github.com/quickfix-j/quickfixj)
Acceptor 配置文件
# 定義會話的默認配置(default節點) [DEFAULT] FileStorePath=store FileLogPath=log ConnectionType=acceptor ReconnectInterval=60 SenderCompID=SERVER ResetOnDisconnect=Y ResetOnLogout=Y ResetOnLogon=Y [SESSION] BeginString=FIX.4.2 TargetCompID=CLIENT StartTime=00:00:00 EndTime=23:59:59 HeartBtInt=30 SocketAcceptHost=127.0.0.1 SocketAcceptPort=6666 DataDictionary=FIX42.xml
Initiator 配置文件
[DEFAULT] ConnectionType=initiator ReconnectInterval=60 FileLogPath=log FileStorePath=store StartTime=00:00:00 EndTime=23:59:59 HeartBtInt=30 ResetOnDisconnect=Y ResetOnLogout=Y ResetOnLogon=Y [SESSION] BeginString=FIX.4.2 SenderCompID=CLIENT TargetCompID=SERVER SocketConnectPort=6666 SocketConnectHost=127.0.0.1 DataDictionary=FIX42.xml
FixServer
package com.app.fix; import quickfix.*; /** * 服務啓動主類(線程) */ public class FixServer { private static ThreadedSocketAcceptor acceptor = null; /** * 指定配置文件啓動 * * @param propFile * @throws ConfigError * @throws FieldConvertError */ public FixServer(String propFile) throws ConfigError, FieldConvertError { // 設置配置文件 SessionSettings settings = new SessionSettings(propFile); // 設置一個APPlication Application application = new FixServerApplication(); /** * * quickfix.MessageStore 有2種實現。 quickfix.JdbcStore,quickfix.FileStore . * JdbcStoreFactory 負責建立JdbcStore , FileStoreFactory 負責建立FileStorequickfix * 默認用文件存儲,由於文件存儲效率高。 */ MessageStoreFactory storeFactory = new FileStoreFactory(settings); LogFactory logFactory = new FileLogFactory(settings); MessageFactory messageFactory = new DefaultMessageFactory(); acceptor = new ThreadedSocketAcceptor(application, storeFactory, settings, logFactory, messageFactory); } private void startServer() throws RuntimeError, ConfigError { acceptor.start(); } /** * 測試本地使用的main方法 * * @param args * @throws FieldConvertError * @throws ConfigError */ public static void main(String[] args) throws ConfigError, FieldConvertError { FixServer fixServer = new FixServer("res/acceptor.config"); fixServer.startServer(); } }
FixServerApplication
package com.app.fix; import quickfix.Application; import quickfix.DoNotSend; import quickfix.FieldNotFound; import quickfix.IncorrectDataFormat; import quickfix.IncorrectTagValue; import quickfix.Message; import quickfix.MessageCracker; import quickfix.RejectLogon; import quickfix.Session; import quickfix.SessionID; import quickfix.UnsupportedMessageType; import quickfix.field.MsgType; /** * */ public class FixServerApplication extends MessageCracker implements Application { @Override protected void onMessage(Message message, SessionID sessionID) { try { String msgType = message.getHeader().getString(35); Session session = Session.lookupSession(sessionID); switch (msgType) { case MsgType.LOGON: // 登錄 session.logon(); session.sentLogon(); break; case MsgType.HEARTBEAT: // 心跳 session.generateHeartbeat(); break; } } catch (FieldNotFound e) { e.printStackTrace(); } } @Override public void onCreate(SessionID sessionId) { System.out.println(" 服務器啓動時候調用此方法建立"); } @Override public void onLogon(SessionID sessionId) { System.out.println("客戶端登錄成功時候調用此方法"); } @Override public void onLogout(SessionID sessionId) { System.out.println("客戶端斷開鏈接時候調用此方法"); } @Override public void toAdmin(Message message, SessionID sessionId) { System.out.println("發送會話消息時候調用此方法"); } @Override public void toApp(Message message, SessionID sessionId) throws DoNotSend { System.out.println("發送業務消息時候調用此方法"); } @Override public void fromAdmin(Message message, SessionID sessionId) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, RejectLogon { System.out.println("接收會話類型消息時調用此方法"); try { crack(message, sessionId); } catch (UnsupportedMessageType | FieldNotFound | IncorrectTagValue e) { e.printStackTrace(); } } @Override public void fromApp(Message message, SessionID sessionId) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType { System.out.println("接收業務消息時調用此方法"); crack(message, sessionId); } }
FixClient
package com.app.fix; import quickfix.*; import quickfix.field.*; import quickfix.fix42.NewOrderSingle; import java.io.FileNotFoundException; import java.util.Date; public class FixClient implements Application { private static volatile SessionID sessionID; @Override public void onCreate(SessionID sessionID) { System.out.println("OnCreate"); } @Override public void onLogon(SessionID sessionID) { System.out.println("OnLogon"); FixClient.sessionID = sessionID; } @Override public void onLogout(SessionID sessionID) { System.out.println("OnLogout"); FixClient.sessionID = null; } @Override public void toAdmin(Message message, SessionID sessionID) { System.out.println("ToAdmin"); } @Override public void fromAdmin(Message message, SessionID sessionID) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, RejectLogon { System.out.println("FromAdmin"); } @Override public void toApp(Message message, SessionID sessionID) throws DoNotSend { System.out.println("ToApp: " + message); } @Override public void fromApp(Message message, SessionID sessionID) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType { System.out.println("FromApp"); } public static void main(String[] args) throws ConfigError, FileNotFoundException, InterruptedException, SessionNotFound { SessionSettings settings = new SessionSettings("res/initiator.config"); Application application = new FixClient(); MessageStoreFactory messageStoreFactory = new FileStoreFactory(settings); LogFactory logFactory = new ScreenLogFactory(true, true, true); MessageFactory messageFactory = new DefaultMessageFactory(); Initiator initiator = new SocketInitiator(application, messageStoreFactory, settings, logFactory, messageFactory); initiator.start(); while (sessionID == null) { Thread.sleep(1000); } final String orderId = "342"; NewOrderSingle newOrder = new NewOrderSingle(new ClOrdID(orderId), new HandlInst('1'), new Symbol("YRD"), new Side(Side.BUY), new TransactTime(new Date()), new OrdType(OrdType.MARKET)); Session.sendToTarget(newOrder, sessionID); Thread.sleep(5000); } }
做者:姜永念
來源:來源:宜信技術學院