通貨ペアの要求 < x > SecurityListRequest に対する返答 < y > SecurityList を受け取ります
返答には利用可能な 通貨ペア 情報がぎっしり?詰め込まれているので、1つ1つ取り出して、DBへ保存しときます
ついでにレート情報の要求も投げ込めるようにしときましょう
レート情報を受け取った後の情報保持用に変数の初期化なんかもやっときます
メッセージ受信 < y > SecurityList
#include "config.h"
#include "Application.h"
#include "quickfix/Session.h"
#include <iostream>
/* y */
void Application::onMessage(const FIX44::SecurityList& message, const FIX::SessionID& sessionID )
{
std::cout << "<y> SecurityList: " << std::endl << message.toXML() << std::endl;
/* Get Message Data */
/* 146 */ FIX::FieldBase symbolCount( FIX::FIELD::NoRelatedSym, "0" );
message.getFieldIfSet( symbolCount );
/* Check Counter - none return */
if(std::stoi(symbolCount.getString()) <= 0) return;
/* UPDATE ALL Status - flase */
FIX::MySQLQuery q( "UPDATE `T_SYMBOL` SET `Status` = 0 WHERE `Status` = 1;" );
m_sql->execute( q );
/* INIT rate vector */
rate.clear();
rate.shrink_to_fit();
rate.resize(std::stoi(symbolCount.getString()));
/* Loop: Currency Pair */
for( int i=1; i <= std::stoi(symbolCount.getString()); i++ )
{
/* 146 */ FIX44::SecurityList::NoRelatedSym r;
message.getGroup(i, r);
/* 55 */ FIX::FieldBase symbol( FIX::FIELD::Symbol, "NA");
r.getFieldIfSet( symbol );
/* SELECT SYMBOL */
bool getRate = false;
std::ostringstream s1;
s1 << "SELECT `Symbol`, `GetRate` FROM `T_SYMBOL` WHERE `Symbol` = '" << symbol << "'";
FIX::MySQLQuery q1( s1.str() );
m_sql->execute( q1 );
/* UPDATE Status - true */
if( q1.rows() != 0 )
{
std::ostringstream s2;
s2 << "UPDATE `T_SYMBOL`" <<
" SET `Status` = 0" <<
" WHERE `Symbol` = '" << symbol << "'";
FIX::MySQLQuery q2( s2.str() );
m_sql->execute( q2 );
/* Get Rate? */
if (std::string(q1.getValue(0,1)) == "1")
getRate = true;
}
/* INSERT SYMBOL Status - true */
else
{
std::ostringstream s3;
s3 << "INSERT INTO `T_SYMBOL` " <<
" ( `Symbol`, `Status` ) " <<
" VALUES ('" << symbol << "', 0 )";
FIX::MySQLQuery q3( s3.str() );
m_sql->execute( q3 );
}
/* Symbol : map - vector */
m_symbol[symbol.getString()] = (i - 1);
rate[ m_symbol[symbol.getString()] ].Symbol = symbol.getString();
rate[ m_symbol[symbol.getString()] ].feedStatus = false;
/* Get Market Data Rate */
if( getRate )
{
/* <V> */ MarketDataRequest(); // symbol.getString() );
}
}
/* End : Currency Pair */
}
ってな感じの処理になってます
T_SYMBOL テーブル
通貨ペアを保存するためのテーブルはこんな感じ
DROP TABLE IF EXISTS T_SYMBOL;
CREATE TABLE T_SYMBOL
(
`Symbol` VARCHAR(7) NOT NULL COMMENT '55 ',
`Status` CHAR(1) NOT NULL DEFAULT 0 COMMENT '---- 0:FALSE 1:TRUE ',
`GetRate` CHAR(1) NOT NULL DEFAULT 0 COMMENT '---- 0:None 1:GetRate ',
`Created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`Updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`Deleted_at` DATETIME NULL,
PRIMARY KEY (`Symbol`)
)
COMMENT 'Symbol List';
INSERT INTO `T_SYMBOL` (`Symbol`, `GetRate`) VALUES ('USD/JPY', '1');
INSERT INTO `T_SYMBOL` (`Symbol`, `GetRate`) VALUES ('EUR/JPY', '1');
INSERT INTO `T_SYMBOL` (`Symbol`, `GetRate`) VALUES ('EUR/USD', '1');
DESC T_SYMBOL;
Status が "0" ならCNEXの対象外通貨ペア
GetRate が "0" ならレート情報の受信は行わない
という感じ
とりあえず3ペアをレート情報受信対象としてレコード追加しときます。
・USD/JPY
・EUR/JPY
・EUR/USD
レート情報保存領域
構造体を定義しときます
typedef struct {
std::string Symbol;
double Bid;
long BidSize;
long BidOrder;
double Spred;
double Ask;
long AskSize;
long AskOrder;
double High;
double Low;
std::string Time;
bool feedStatus;
} Rate;
Application.h ヘッダーファイル
レート情報保存領域とかの準備を
@@ -37,6 +37,8 @@
#include "resp_CG_PartyDetailsListReport.h" // resp < CG >
#include "resp_PU_OrderRateUpdate.h" // resp < PU >
+#include "Rate.h"
+
#include <queue>
#include <vector>
#include <map>
@@ -84,6 +86,9 @@ private:
std::string m_accountID;
std::string m_partyID;
+ std::map<std::string, int> m_symbol;
+ std::vector<Rate> rate;
+
void onCreate( const FIX::SessionID& ) {}
void onLogon( const FIX::SessionID& sessionID );
void onLogout( const FIX::SessionID& sessionID );
ヘッダーファイル Rate.h を読み込んで、保存領域を宣言
make 対象に追加
@@ -4,6 +4,7 @@ tradeclient_SOURCES = \
tradeclient.cpp \
Application.h \
Application.cpp \
+ Rate.h \
resp_8__ExecutionReport.cpp \
resp_9__OrderCancelReject.cpp \
resp_AO_RequestForPositionsAck.cpp \
コンパイル
tradeclient]$ make clean
tradeclient]$ make
エラーなく終了すること
受信メッセージサンプル
8=FIX.4.4
9=939
35=y
49=CNX
34=3
52=20170412-15:39:30.879
56=Demo_Trd
320=SecListReq_20170412-153930.773
322=1
560=0
146=19
55=USD/JPY 870=2 871=18 872=2 871=16 872=2
55=AUD/CHF 870=2 871=18 872=4 871=16 872=4
55=USD/CHF 870=2 871=18 872=4 871=16 872=4
55=AUD/USD 870=2 871=18 872=4 871=16 872=4
55=EUR/CHF 870=2 871=18 872=4 871=16 872=4
55=EUR/AUD 870=2 871=18 872=4 871=16 872=4
55=EUR/GBP 870=2 871=18 872=4 871=16 872=4
55=EUR/JPY 870=2 871=18 872=2 871=16 872=2
55=EUR/USD 870=2 871=18 872=4 871=16 872=4
55=GBP/USD 870=2 871=18 872=4 871=16 872=4
55=ZAR/JPY 870=2 871=18 872=2 871=16 872=2
55=NZD/USD 870=2 871=18 872=4 871=16 872=4
55=GBP/CHF 870=2 871=18 872=4 871=16 872=4
55=CHF/JPY 870=2 871=18 872=2 871=16 872=2
55=CAD/CHF 870=2 871=18 872=4 871=16 872=4
55=GBP/JPY 870=2 871=18 872=2 871=16 872=2
55=AUD/JPY 870=2 871=18 872=2 871=16 872=2
55=CAD/JPY 870=2 871=18 872=2 871=16 872=2
55=NZD/JPY 870=2 871=18 872=2 871=16 872=2
10=156
こんな感じのメッセージを受け取るハズ
<前 【QuickFIX】08 通貨ペア要求 SecurityListRequest
次> 【QuickFIX】10 デモ環境サーバへ接続
一覧
01 サンプルのコンパイル
02 ログイン時にPassword(554)を送信
03 送受信ログをMySQLに保存
04 情報保存用にMySQLコネクションを保持..他
05 各種メッセージの枠を作成
06 独自メッセージ仕様
07 セッション開始 TradingSessionStatus
08 通貨ペア要求 SecurityListRequest
09 通貨ペア取得 SecurityList
10 デモ環境サーバへ接続
11 ログ出力設定
12 マーケット情報要求 < V > MarketDataRequest
13 マーケット情報受信 < X > MarketDataIncrementalRefresh
14 口座情報要求 < AN > RequestForPositions
15 口座情報取得 < AZ > CollateralResponse