<前 【QuickFIX】03 送受信ログをMySQLに保存
次> 【QuickFIX】05 各種メッセージの枠を作成
取引情報やレート情報を保存するためのMySQLコネクションを保持できるようにしときます。
その他もろもろ?設定とかごみ削除とか
##Applicationヘッダーファイル
#ifndef TRADECLIENT_APPLICATION_H
#define TRADECLIENT_APPLICATION_H
#include "quickfix/Application.h"
#include "quickfix/MessageCracker.h"
#include "quickfix/Values.h"
#include "quickfix/Mutex.h"
★ #include "quickfix/MySQLConnection.h"
#include <queue>
★ #include <vector>
★ #include <map>
★ const char SessionTypeTrade [] = "Trade";
★ const char SessionTypeRatefeed [] = "Ratefeed";
★ const char AppDEFAULT_DATABASE[] = "quickfix";
★ const char AppDEFAULT_USER[] = "root";
★ const char AppDEFAULT_PASS[] = "";
★ const char AppDEFAULT_HOST[] = "localhost";
★ const short AppDEFAULT_PORT = 3306;
class Application :
public FIX::Application,
public FIX::MessageCracker
{
public:
Application( const FIX::SessionSettings& settings )
: m_settings( settings )
★ {
★ m_sql = MySQLConnect();
★ m_accountID = getSetting("AccountID");
★ m_partyID = getSetting("PartyID");
★ m_tradeSessionStatus = false;
★ m_ratefeedSessionStatus = false;
★ }
★ ~Application()
★ {
★ if (m_sql) delete m_sql;
★ }
void run();
private:
FIX::SessionSettings m_settings;
★ FIX::MySQLConnection *m_sql;
★ std::string m_database;
★ std::string m_user;
★ std::string m_pass;
★ std::string m_host;
★ short m_port;
★ bool m_tradeSessionStatus;
★ bool m_ratefeedSessionStatus;
★ std::map<std::string, std::string> m_senderID;
★ std::map<std::string, std::string> m_targetID;
★ std::string m_accountID;
★ std::string m_partyID;
void onCreate( const FIX::SessionID& ) {}
void onLogon( const FIX::SessionID& sessionID );
void onLogout( const FIX::SessionID& sessionID );
void toAdmin( FIX::Message&, const FIX::SessionID& );
void toApp( FIX::Message&, const FIX::SessionID& )
throw( FIX::DoNotSend );
void fromAdmin( const FIX::Message&, const FIX::SessionID& )
throw( FIX::FieldNotFound, FIX::IncorrectDataFormat, FIX::IncorrectTagValue, FIX::RejectLogon ) {}
void fromApp( const FIX::Message& message, const FIX::SessionID& sessionID )
throw( FIX::FieldNotFound, FIX::IncorrectDataFormat, FIX::IncorrectTagValue, FIX::UnsupportedMessageType );
★ void SetMessageHeader( FIX::Message&, const char* = SessionTypeTrade );
★ FIX::MySQLConnection *MySQLConnect();
★ std::string getSetting( const char* );
★ std::string YmdHMSs( const char* = "%04d%02d%02d-%02d%02d%02d.%03d" );
};
#endif
##Applicationソースファイル
#include "config.h"
#include "Application.h"
#include "quickfix/Session.h"
#include <iostream>
void Application::onLogon( const FIX::SessionID& sessionID )
{
std::cout << std::endl << "Logon - " << sessionID << std::endl;
}
void Application::onLogout( const FIX::SessionID& sessionID )
{
std::cout << std::endl << "Logout - " << sessionID << std::endl;
}
void Application::fromApp( const FIX::Message& message, const FIX::SessionID& sessionID )
throw( FIX::FieldNotFound, FIX::IncorrectDataFormat, FIX::IncorrectTagValue, FIX::UnsupportedMessageType )
{
crack( message, sessionID );
std::cout << std::endl << "IN: " << message << std::endl;
}
void Application::toAdmin( FIX::Message& message, const FIX::SessionID& sessionID )
{
if (FIX::MsgType_Logon == message.getHeader().getField(FIX::FIELD::MsgType))
{
const FIX::Dictionary& dic = m_settings.get( sessionID );
if (dic.has("Password"))
message.getHeader().setField(FIX::Password(dic.getString("Password")));
}
}
void Application::toApp( FIX::Message& message, const FIX::SessionID& sessionID )
throw( FIX::DoNotSend )
{
try
{
FIX::PossDupFlag possDupFlag;
message.getHeader().getField( possDupFlag );
if ( possDupFlag ) throw FIX::DoNotSend();
}
catch ( FIX::FieldNotFound& ) {}
std::cout << std::endl
<< "OUT: " << message << std::endl;
}
void Application::run()
{
while ( true )
{
try
{
std::string action;
★ std::cout << "------ " << YmdHMSs("%04d/%02d/%02d %02d:%02d:%02d.%03d" ) << " --------" << std::endl
<< "quit) Quit" << std::endl
<< "Action: ";
std::cin >> action;
if ( action == "quit" )
break;
}
catch ( std::exception & e )
{
std::cout << "Message Not Sent: " << e.what();
}
}
}
★ void Application::SetMessageHeader( FIX::Message& message, const char* sessionType )
★ {
★ auto itr = m_senderID.find(sessionType);
★ if (itr == m_senderID.end())
★ {
★ const std::set <FIX::SessionID> session = m_settings.getSessions();
★ for (std::set <FIX::SessionID>::iterator it = session.begin(); it != session.end(); ++it)
★ {
★ const FIX::Dictionary dic = m_settings.get( *it );
★ if (dic.getString("SessionType") == sessionType)
★ {
★ m_senderID[dic.getString("SessionType")] = dic.getString("SenderCompID");
★ m_targetID[dic.getString("SessionType")] = dic.getString("TargetCompID");
★ break;
★ }
★ }
★ }
★ message.getHeader().setField((FIX::SenderCompID)m_senderID[sessionType]);
★ message.getHeader().setField((FIX::TargetCompID)m_targetID[sessionType]);
★ }
★ FIX::MySQLConnection *Application::MySQLConnect()
★ {
★ if (m_database == "")
★ {
★ m_database = AppDEFAULT_DATABASE;
★ m_user = AppDEFAULT_USER;
★ m_pass = AppDEFAULT_PASS;
★ m_host = AppDEFAULT_HOST;
★ m_port = AppDEFAULT_PORT;
★ const FIX::Dictionary dic = m_settings.get();
★ if (dic.has("MySQLStoreDatabase")) m_database = dic.getString("MySQLStoreDatabase");
★ if (dic.has("MySQLStoreUser")) m_user = dic.getString("MySQLStoreUser");
★ if (dic.has("MySQLStorePassword")) m_pass = dic.getString("MySQLStorePassword");
★ if (dic.has("MySQLStoreHost")) m_host = dic.getString("MySQLStoreHost");
★ if (dic.has("MySQLStorePort")) m_port = dic.getInt("MySQLStorePort");
★ }
★ return new FIX::MySQLConnection( m_database, m_user, m_pass, m_host, m_port );
★ }
★ std::string Application::getSetting( const char* key )
★ {
★ const FIX::Dictionary dic = m_settings.get();
★ if (dic.has(key)) return dic.getString(key);
★ return key;
★ }
★ std::string Application::YmdHMSs( const char* format )
★ {
★ FIX::UtcTimeStamp time;
★ int year, month, day, hour, minute, second, millis;
★ time.getYMD( year, month, day );
★ time.getHMS( hour, minute, second, millis );
★ char tm[ 30 ];
★ // YYYYmmdd-HHMMSS.sss "%04d%02d%02d-%02d%02d%02d.%03d"
★ // 1234567890123456789
★ STRING_SPRINTF( tm, format, year, month, day, hour, minute, second, millis );
★ return tm;
★ }
##コンパイル
tradeclient]$ make clean
tradeclient]$ make
##設定ファイルに項目追加
[DEFAULT]
ConnectionType=initiator
ReconnectInterval=60
FileStorePath=store
FileLogPath=log
StartTime=00:00:00
EndTime=00:00:00
UseDataDictionary=Y
DataDictionary=FIX44.xml
HttpAcceptPort=9911
ValidateUserDefinedFields=N
ResetOnLogout=Y
ResetOnLogon=Y
# -- MySQL Store ----
MySQLStoreDatabase=Quick
MySQLStoreUser=QuickUSER
MySQLStorePassword=QuickPASS
MySQLStoreHost=localhost
# -- MySQL Log ------
MySQLLogDatabase=Quick
MySQLLogUser=QuickUSER
MySQLLogPassword=QuickPASS
MySQLLogHost=localhost
# -- Account ------
AccountID=CAXDemo_Account
PartyID=CAXDemo_Account
[SESSION]
BeginString=FIX.4.4
SenderCompID=CAXDemo_Account_Trd
TargetCompID=CNX
SocketConnectHost=127.0.0.1
SocketConnectPort=9999
HeartBtInt=30
Password=Pass1234
SessionType=Trade
[SESSION]
BeginString=FIX.4.4
SenderCompID=CAXDemo_Account_Str
TargetCompID=CNX
SocketConnectHost=127.0.0.1
SocketConnectPort=9999
HeartBtInt=30
Password=Pass1234
SessionType=Ratefeed
###動作確認
tradeclient]$ ./tradeclient tradeclient.cfg
------ 2017/04/12 04:49:53.866 --------
quit) Quit
Action:
Logout - FIX.4.4:CAXDemo_Account_Str->CNX
Logout - FIX.4.4:CAXDemo_Account_Trd->CNX
quit
tradeclient]$
ちゃんと動いてます。ね。
DB確認
tradeclient]$ mysql -u QuickUSER -p Quick
select sendercompid
, targetcompid
, replace(message,char(1),' ') as 'message'
from messages
;
+---------------------+--------------+------------------------------------------------------------------------------------------------------------------------+
| sendercompid | targetcompid | message |
+---------------------+--------------+------------------------------------------------------------------------------------------------------------------------+
| CAXDemo_Account_Str | CNX | 8=FIX.4.4 9=96 35=A 34=1 49=CAXDemo_Account_Str 52=20170412-04:49:53.943 56=CNX 554=Pass1234 98=0 108=30 141=Y 10=135 |
| CAXDemo_Account_Trd | CNX | 8=FIX.4.4 9=96 35=A 34=1 49=CAXDemo_Account_Trd 52=20170412-04:49:54.046 56=CNX 554=Pass1234 98=0 108=30 141=Y 10=115 |
+---------------------+--------------+------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
DBにもちゃんと保存されてる
<前 【QuickFIX】03 送受信ログをMySQLに保存
次> 【QuickFIX】05 各種メッセージの枠を作成
一覧
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