< AN > RequestForPositions の返信メッセージの < AZ > CollateralResponse で口座情報を取得して残高とかを保存しときます。
< AZ > CollateralResponse
#include "config.h"
#include "Application.h"
#include "quickfix/Session.h"
#include <iostream>
/* AZ */
void Application::onMessage(const FIX44::CollateralResponse& message, const FIX::SessionID& sessionID )
{
// std::cout << "<AZ> CollateralResponse: " << std::endl << message.toXML() << std::endl;
LOG_DEBUG << "<AZ> CollateralResponse: " << std::endl << message;
LOG_VERBOSE << "<AZ> CollateralResponse: " << std::endl << message.toXML();
/* Get Account ID */
/* 1 */ FIX::FieldBase accountID(FIX::FIELD::Account, m_accountID);
message.getFieldIfSet( accountID );
/* Get Currency */
/* 15 */ FIX::FieldBase currency(FIX::FIELD::Currency, "NA");
message.getFieldIfSet( currency );
/* Get Transact Time */
/* 60 */ FIX::FieldBase transactTime(FIX::FIELD::TransactTime, "");
message.getFieldIfSet( transactTime );
std::string transactDay = transactTime.getString().substr(0,8);
/* Get Financial Status 1:Disable 3:Active */
/* 291 */ FIX::FieldBase status(FIX::FIELD::FinancialStatus, "0");
message.getFieldIfSet( status );
/* Get MarginRatio */
/* 898 */ FIX::FieldBase ratio(FIX::FIELD::MarginRatio, "0");
message.getFieldIfSet( ratio );
/* Get Response Type */
/* 905 */ FIX::FieldBase result(FIX::FIELD::CollAsgnRespType, "0");
message.getFieldIfSet( result );
/* Get Start Cash - Trading Day Opening Balance */
/* 921 */ FIX::FieldBase startCash(FIX::FIELD::StartCash, "0");
message.getFieldIfSet( startCash );
/* Get End Cash - Current Balance - max 40億 */
/* 922 */ FIX::FieldBase endCash(FIX::FIELD::EndCash, "0");
message.getFieldIfSet( endCash );
/* Insert into Balance Hist */
std::ostringstream s1;
s1 << "INSERT INTO `T_BALANCE_HIST` " <<
" ( " <<
" `Account` " << /* 1 */
" , `Result` " << /* 905 1:Accepted 3:Reject */
" , `TransactTime` " << /* 60 yyyymmdd-hh:mm:ss */
" , `TransactDay` " << /* 60 yyyymmdd */
" , `FinansialStatus` " << /* 291 1=Disabled 3:Active */
" , `Currency` " << /* 15 */
" , `MarginRatio` " << /* 898 */
" , `StartCash` " << /* 921 */
" , `EndCash` " << /* 922 */
" ) VALUES ( " <<
" '" << accountID << "' " << /* 1 */
" , '" << result << "' " << /* 905 */
" , '" << transactTime << "' " << /* 60 */
" , '" << transactDay << "' " << /* 60 */
" , '" << status << "' " << /* 291 */
" , '" << currency << "' " << /* 15 */
" , '" << ratio << "' " << /* 898 */
" , '" << startCash << "' " << /* 921 */
" , '" << endCash << "' " << /* 922 */
" ) ";
FIX::MySQLQuery q1( s1.str() );
if( m_sql->execute( q1 ) != true )
{
LOG_WARNING << "INSERT ERROR T_BALANCE_HIST :" << q1.reason() << std::endl << s1.str();
}
else
{
LOG_VERBOSE << "INSERT T_BALANCE_HIST : " << q1.reason() << std::endl << s1.str();
}
/* reject ? */
if( result.getString() != "1" ) return;
/* finansial status disable ? */
if( status.getString() != "3" ) return;
/* Update Current Balance */
std::ostringstream s2;
s2 << "UPDATE `T_BALANCE` " <<
" SET `TransactTime` = '" << transactTime << "' " << /* 60 */
" , `Currency` = '" << currency << "' " << /* 15 */
" , `MarginRatio` = '" << ratio << "' " << /* 898 */
" , `StartCash` = '" << startCash << "' " << /* 921 */
" , `EndCash` = '" << endCash << "' " << /* 922 */
" WHERE `Account` = '" << accountID << "' " << /* 1 */
"";
FIX::MySQLQuery q2( s2.str() );
if( m_sql->execute( q2 ) != true )
{
LOG_WARNING << "UPDATE ERROR T_BALANCE :" << q2.reason() << std::endl << s2.str();
}
else
{
LOG_VERBOSE << "UPDATE T_BALANCE : " << q2.reason() << std::endl << s2.str();
}
/* set current cash & ratio */
m_cash = std::stoul(endCash.getString());
m_ratio = std::stof(ratio.getString());
if(m_start_cash == 0)
m_start_cash = m_cash;
/* normal return */
return;
}
口座状況や残高情報を取得
DBとメモリに保存しちゃいます
残高情報をメモリに保持できるように宣言
・・・
public:
Application( const FIX::SessionSettings& settings )
: m_settings( settings )
{
m_sql = MySQLConnect();
m_accountID = getSetting("AccountID");
m_partyID = getSetting("PartyID");
m_tradingSessionStatus = 0;
★ m_cash = 1000000000;
★ m_start_cash = 0;
★ m_ratio = 1.0;
plog::init( (plog::Severity)std::stoi(getSetting("LOGLevel", "3")) // default warning(3)
, std::string(getSetting("LOGFile", "tradeclient") + YmdHMS(".%Y%m%d.log")).c_str() // default filename
, std::stoul(getSetting("LOGMaxSize", "10240000")) // default 10MB=10,240,000byte
, std::stoi(getSetting("LOGMaxFiles", "10")) ); // default files= 10
}
~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;
int m_tradingSessionStatus;
std::map<std::string, std::string> m_senderID;
std::map<std::string, std::string> m_targetID;
std::string m_accountID;
std::string m_partyID;
std::map<std::string, int> m_symbol;
std::vector<Rate> rate;
★ unsigned long m_cash;
★ unsigned long m_start_cash;
★ float m_ratio;
・・・
残高情報を保持するように宣言して、初期化してます
独自フィールド対応
標準とは必須とかフィールドとか値とかが違うので対応
(前にやった時の作業漏れ)
・・・
<message name='CollateralResponse' msgtype='AZ' msgcat='app'>
<field name='CollRespID' required='Y' />
- <field name='CollAsgnID' required='Y' />
+ <field name='CollAsgnID' required='N' />
<field name='CollReqID' required='N' />
- <field name='CollAsgnReason' required='Y' />
+ <field name='CollAsgnReason' required='N' />
<field name='CollAsgnTransType' required='N' />
<field name='CollAsgnRespType' required='Y' />
<field name='CollAsgnRejectReason' required='N' />
<field name='TransactTime' required='Y' />
+ <field name='FinancialStatus' required='Y' />
<component name='Parties' required='N' />
<field name='Account' required='N' />
<field name='AccountType' required='N' />
<field name='ClOrdID' required='N' />
<field name='OrderID' required='N' />
<field name='SecondaryOrderID' required='N' />
<field name='SecondaryClOrdID' required='N' />
<component name='ExecCollGrp' required='N' />
<component name='TrdCollGrp' required='N' />
<component name='Instrument' required='N' />
<component name='FinancingDetails' required='N' />
<field name='SettlDate' required='N' />
<field name='Quantity' required='N' />
<field name='QtyType' required='N' />
<field name='Currency' required='N' />
<component name='InstrmtLegGrp' required='N' />
<component name='UndInstrmtCollGrp' required='N' />
<field name='MarginExcess' required='N' />
<field name='TotalNetValue' required='N' />
<field name='CashOutstanding' required='N' />
<component name='TrdRegTimestamps' required='N' />
<field name='Side' required='N' />
<component name='MiscFeesGrp' required='N' />
<field name='Price' required='N' />
<field name='PriceType' required='N' />
<field name='AccruedInterestAmt' required='N' />
<field name='EndAccruedInterestAmt' required='N' />
<field name='StartCash' required='N' />
<field name='EndCash' required='N' />
<component name='SpreadOrBenchmarkCurveData' required='N' />
<component name='Stipulations' required='N' />
<field name='Text' required='N' />
<field name='EncodedTextLen' required='N' />
<field name='EncodedText' required='N' />
</message>
・・・
<field number='291' name='FinancialStatus' type='MULTIPLEVALUESTRING'>
<value enum='1' description='BANKRUPT' />
<value enum='2' description='PENDING_DELISTING' />
+ <value enum='3' description='RESTRICTED' />
</field>
・・・
動作確認用
受け取った口座情報を表示できるようにしときます
・・・
void Application::run()
{
while ( true )
{
try
{
std::string action;
std::cout << "------ " << YmdHMSs("%04d/%02d/%02d %02d:%02d:%02d.%03d" ) << " --------" << std::endl
<< "q) Quit" << std::endl
★ << "r) Show rate " << std::endl
<< "Action: ";
std::cin >> action;
LOG_DEBUG << "COMMAND: " << action;
if ( action == "q" )
break;
else
★ if ( action == "r" )
{
★ RequestForPositions( YmdHMS("%Y%m%d") );
★ std::cout <<
★ "START : " << std::setw(15) << std::right << numFormat(m_start_cash) << std::endl <<
★ "CURRENT: " << std::setw(15) << std::right << numFormat(m_cash) << std::endl <<
★ "RATIO : " << m_ratio << std::endl;
for( auto symbol: m_symbol)
{
if(rate[symbol.second].feedStatus)
{
std::ostringstream s;
// s << std::fixed;
s << std::setprecision(8) ;
s << symbol.first << "\t"
<< rate[symbol.second].Time << " "
<< rate[symbol.second].Symbol << " "
<< rate[symbol.second].Bid << " \t"
<< rate[symbol.second].Spred << " \t"
<< rate[symbol.second].Ask << " "
<< std::endl;
std::cout << s.str();
}
}
}
}
catch ( std::exception & e )
{
std::cout << "Message Not Sent: " << e.what();
LOG_WARNING << "Message Not Sent: " << e.what();
}
}
}
・・・
メニューで r を入力すると口座情報を要求して
最新の口座情報を表示する
DB保存
保存されていることを確認しとく
mysql> select *
-> from T_BALANCE;
+-----------------+-------------------+----------+-------------+------------+------------+---------------------+---------------------+------------+
| Account | TransactTime | Currency | MarginRatio | StartCash | EndCash | Created_at | Updated_at | Deleted_at |
+-----------------+-------------------+----------+-------------+------------+------------+---------------------+---------------------+------------+
| CAXDemo_Account | 20170424-15:04:25 | JPY | 1 | 1000003830 | 1000003830 | 2017-04-24 23:33:23 | 2017-04-25 00:04:25 | NULL |
+-----------------+-------------------+----------+-------------+------------+------------+---------------------+---------------------+------------+
1 row in set (0.02 sec)
履歴も確認
mysql> select *
-> from T_BALANCE_HIST
-> limit 16, 100;
+----+-----------------+--------+-------------------+-------------+-----------------+----------+-------------+------------+------------+---------------------+
| id | Account | Result | TransactTime | TransactDay | FinansialStatus | Currency | MarginRatio | StartCash | EndCash | Created_at |
+----+-----------------+--------+-------------------+-------------+-----------------+----------+-------------+------------+------------+---------------------+
| 17 | CAXDemo_Account | 1 | 20170424-14:55:38 | 20170424 | 3 | JPY | 1 | 1000003830 | 1000003830 | 2017-04-24 23:55:38 |
| 18 | CAXDemo_Account | 1 | 20170424-14:55:40 | 20170424 | 3 | JPY | 1 | 1000003830 | 1000003830 | 2017-04-24 23:55:41 |
| 19 | CAXDemo_Account | 1 | 20170424-14:55:42 | 20170424 | 3 | JPY | 1 | 1000003830 | 1000003830 | 2017-04-24 23:55:43 |
| 20 | CAXDemo_Account | 1 | 20170424-14:55:43 | 20170424 | 3 | JPY | 1 | 1000003830 | 1000003830 | 2017-04-24 23:55:43 |
| 21 | CAXDemo_Account | 1 | 20170424-14:57:30 | 20170424 | 3 | JPY | 1 | 1000003830 | 1000003830 | 2017-04-24 23:57:30 |
| 22 | CAXDemo_Account | 1 | 20170424-14:57:32 | 20170424 | 3 | JPY | 1 | 1000003830 | 1000003830 | 2017-04-24 23:57:32 |
| 23 | CAXDemo_Account | 1 | 20170424-15:02:34 | 20170424 | 3 | JPY | 1 | 1000003830 | 1000003830 | 2017-04-25 00:02:34 |
| 24 | CAXDemo_Account | 1 | 20170424-15:03:32 | 20170424 | 3 | JPY | 1 | 1000003830 | 1000003830 | 2017-04-25 00:03:32 |
| 25 | CAXDemo_Account | 1 | 20170424-15:04:25 | 20170424 | 3 | JPY | 1 | 1000003830 | 1000003830 | 2017-04-25 00:04:25 |
+----+-----------------+--------+-------------------+-------------+-----------------+----------+-------------+------------+------------+---------------------+
9 rows in set (0.00 sec)
<前 【QuickFIX】14 口座情報要求 < AN > RequestForPositions
一覧
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