|
|
@@ -147,14 +147,16 @@ void CPluginInstance::OnOrderDelete(const IMTOrder * order)
|
|
|
}
|
|
|
|
|
|
char order_buf[128];
|
|
|
- sprintf(order_buf, "%lld", order->Order());
|
|
|
+ sprintf(order_buf, "%lld", order->PositionID());
|
|
|
IMTAccount* account = m_api->UserCreateAccount();
|
|
|
IMTOrder* new_order = m_api->OrderCreate();
|
|
|
|
|
|
ScopeGuard guard([account, new_order]
|
|
|
{
|
|
|
- account->Release();
|
|
|
- new_order->Release();
|
|
|
+ if (account)
|
|
|
+ account->Release();
|
|
|
+ if (new_order)
|
|
|
+ new_order->Release();
|
|
|
});
|
|
|
|
|
|
// 订单在进入filled状态时,也会产生一个order delete回调
|
|
|
@@ -178,6 +180,8 @@ void CPluginInstance::OnOrderDelete(const IMTOrder * order)
|
|
|
UINT init_volume_ext = round((double)level * order->VolumeInitialExt() / 10000) * 100;
|
|
|
UINT64 new_order_id = 0;
|
|
|
|
|
|
+ m_api->LoggerOut(MTLogOK, L"add order, vol_init: %lld, vol_cur: %lld", init_volume, volume);
|
|
|
+
|
|
|
// 尚未完成建仓,目前position id不填,仅完成订单后记录
|
|
|
new_order->Clear();
|
|
|
new_order->VolumeInitial(init_volume);
|
|
|
@@ -187,31 +191,29 @@ void CPluginInstance::OnOrderDelete(const IMTOrder * order)
|
|
|
new_order->Type(order->Type());
|
|
|
new_order->Digits(order->Digits());
|
|
|
new_order->DigitsCurrency(order->DigitsCurrency());
|
|
|
- //new_order->ContractSize(order->ContractSize());
|
|
|
+ new_order->ContractSize(order->ContractSize());
|
|
|
new_order->PriceOrder(order->PriceOrder());
|
|
|
- //new_order->PriceCurrent(order->PriceCurrent());
|
|
|
- // State不能填PARTIAL FILLED REJECTED EXPIRED
|
|
|
- new_order->StateSet(IMTOrder::ORDER_STATE_STARTED);
|
|
|
- new_order->TimeSetup(m_api->TimeCurrent());
|
|
|
- new_order->TimeSetupMsc(m_api->TimeCurrentMsc());
|
|
|
- // 一定不能填入time done
|
|
|
- //new_order->TimeDone(order->TimeDone());
|
|
|
- //new_order->TimeDoneMsc(order->TimeDoneMsc());
|
|
|
+ new_order->PriceCurrent(order->PriceCurrent());
|
|
|
+ new_order->StateSet(order->State());
|
|
|
+ new_order->TimeSetup(order->TimeSetup());
|
|
|
+ new_order->TimeSetupMsc(order->TimeSetupMsc());
|
|
|
+ new_order->TimeDone(order->TimeDone());
|
|
|
+ new_order->TimeDoneMsc(order->TimeDoneMsc());
|
|
|
// --
|
|
|
- //new_order->PriceSL(order->PriceSL());
|
|
|
- //new_order->PriceTP(order->PriceTP());
|
|
|
- //new_order->Comment(order->Comment());
|
|
|
- //new_order->ActivationFlags(order->ActivationFlags());
|
|
|
- //new_order->ActivationMode(order->ActivationMode());
|
|
|
- //new_order->ActivationPrice(order->ActivationPrice());
|
|
|
- //new_order->ActivationTime(order->ActivationTime());
|
|
|
- //new_order->PriceTrigger(order->PriceTrigger());
|
|
|
- //new_order->RateMargin(order->RateMargin()); //
|
|
|
- //new_order->ReasonSet(order->Reason()); //
|
|
|
- //new_order->TypeFill(order->TypeFill()); //
|
|
|
- //new_order->TypeTime(order->TypeTime()); //
|
|
|
-
|
|
|
- MTAPIRES ret = m_api->OrderAdd(new_order);
|
|
|
+ new_order->PriceSL(order->PriceSL());
|
|
|
+ new_order->PriceTP(order->PriceTP());
|
|
|
+ new_order->Comment(order->Comment());
|
|
|
+ new_order->ActivationFlags(order->ActivationFlags());
|
|
|
+ new_order->ActivationMode(order->ActivationMode());
|
|
|
+ new_order->ActivationPrice(order->ActivationPrice());
|
|
|
+ new_order->ActivationTime(order->ActivationTime());
|
|
|
+ new_order->PriceTrigger(order->PriceTrigger());
|
|
|
+ new_order->RateMargin(order->RateMargin()); //
|
|
|
+ new_order->ReasonSet(order->Reason()); //
|
|
|
+ new_order->TypeFill(order->TypeFill()); //
|
|
|
+ new_order->TypeTime(order->TypeTime()); //
|
|
|
+
|
|
|
+ MTAPIRES ret = m_api->HistoryAdd(new_order);
|
|
|
if (ret != MT_RET_OK)
|
|
|
{
|
|
|
m_api->LoggerOut(MTLogErr, L"%lld failed to add order, original order #%lld [%d]", login, order->Login(), ret);
|
|
|
@@ -234,13 +236,14 @@ void CPluginInstance::OnOrderDelete(const IMTOrder * order)
|
|
|
direction = -1;
|
|
|
context.volume = direction * order->VolumeInitial();
|
|
|
|
|
|
- auto fut = m_redis_client->hset(order_buf, login_buf, std::string((char*)&context, sizeof(context)));
|
|
|
- m_redis_client->sync_commit();
|
|
|
- auto rep = fut.get();
|
|
|
- if (rep.ko())
|
|
|
+ m_redis_client->hset(order_buf, login_buf, std::string((char*)&context, sizeof(position_context)), [this](cpp_redis::reply& r)
|
|
|
{
|
|
|
- // FIXME: 错误处理
|
|
|
- }
|
|
|
+ if (r.ko())
|
|
|
+ {
|
|
|
+ m_api->LoggerOut(MTLogErr, L"redis: %s", r.error().c_str());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ m_redis_client->commit();
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
@@ -254,9 +257,13 @@ void CPluginInstance::OnOrderDelete(const IMTOrder * order)
|
|
|
m_redis_client->sync_commit();
|
|
|
auto reply = fut.get();
|
|
|
|
|
|
+ m_api->LoggerOut(MTLogOK, L"request cache, key %s, field %s", s2ws(order_buf).c_str(), s2ws(login_buf).c_str());
|
|
|
+
|
|
|
// 如果不存在,忽略
|
|
|
if (reply.ko()) continue;
|
|
|
- if (reply.is_null()) continue;
|
|
|
+ if (reply.is_null()) continue;
|
|
|
+
|
|
|
+ m_api->LoggerOut(MTLogOK, L"get context, login: %lld", login);
|
|
|
|
|
|
// 获取context
|
|
|
position_context context;
|
|
|
@@ -264,7 +271,9 @@ void CPluginInstance::OnOrderDelete(const IMTOrder * order)
|
|
|
|
|
|
// 按建仓时的叙述,如果level或者position为0,亦忽略该记录
|
|
|
if (context.level == 0) continue;
|
|
|
- if (context.position_id == 0) continue;
|
|
|
+ if (context.position_id == 0) continue;
|
|
|
+
|
|
|
+ m_api->LoggerOut(MTLogOK, L"get context, order: #%lld, position: #%lld", context.cur_ord, context.position_id);
|
|
|
|
|
|
// 如果存在,则继续操作
|
|
|
UINT volume = round((double)context.level * order->VolumeCurrent() / 10000) * 100;
|
|
|
@@ -275,22 +284,37 @@ void CPluginInstance::OnOrderDelete(const IMTOrder * order)
|
|
|
|
|
|
new_order->Clear();
|
|
|
new_order->VolumeInitial(init_volume);
|
|
|
- new_order->VolumeCurrent(volume);
|
|
|
+ new_order->VolumeCurrent(volume); // 这里是状态START,如果是状态4的FILLED时,volume current为0
|
|
|
+ //new_order->VolumeCurrent(init_volume);
|
|
|
new_order->Login(login);
|
|
|
new_order->Symbol(order->Symbol());
|
|
|
new_order->Type(order->Type());
|
|
|
new_order->Digits(order->Digits());
|
|
|
new_order->DigitsCurrency(order->DigitsCurrency());
|
|
|
- //new_order->ContractSize(order->ContractSize());
|
|
|
+ new_order->ContractSize(order->ContractSize());
|
|
|
new_order->PriceOrder(order->PriceOrder());
|
|
|
- //new_order->PriceCurrent(order->PriceCurrent());
|
|
|
- // State不能填PARTIAL FILLED REJECTED EXPIRED
|
|
|
- new_order->StateSet(IMTOrder::ORDER_STATE_STARTED);
|
|
|
- new_order->TimeSetup(m_api->TimeCurrent());
|
|
|
- new_order->TimeSetupMsc(m_api->TimeCurrentMsc());
|
|
|
+ new_order->PriceCurrent(order->PriceCurrent());
|
|
|
+ new_order->StateSet(order->State());
|
|
|
+ new_order->TimeSetup(order->TimeSetup());
|
|
|
+ new_order->TimeSetupMsc(order->TimeSetupMsc());
|
|
|
+ new_order->TimeDone(order->TimeDone());
|
|
|
+ new_order->TimeDoneMsc(order->TimeDoneMsc());
|
|
|
new_order->PositionID(context.position_id);
|
|
|
|
|
|
- MTAPIRES ret = m_api->OrderAdd(new_order);
|
|
|
+ new_order->PriceSL(order->PriceSL());
|
|
|
+ new_order->PriceTP(order->PriceTP());
|
|
|
+ new_order->Comment(order->Comment());
|
|
|
+ new_order->ActivationFlags(order->ActivationFlags());
|
|
|
+ new_order->ActivationMode(order->ActivationMode());
|
|
|
+ new_order->ActivationPrice(order->ActivationPrice());
|
|
|
+ new_order->ActivationTime(order->ActivationTime());
|
|
|
+ new_order->PriceTrigger(order->PriceTrigger());
|
|
|
+ new_order->RateMargin(order->RateMargin()); //
|
|
|
+ new_order->ReasonSet(order->Reason()); //
|
|
|
+ new_order->TypeFill(order->TypeFill()); //
|
|
|
+ new_order->TypeTime(order->TypeTime()); //
|
|
|
+
|
|
|
+ MTAPIRES ret = m_api->HistoryAdd(new_order);
|
|
|
if (ret != MT_RET_OK)
|
|
|
{
|
|
|
m_api->LoggerOut(MTLogErr, L"%lld failed to add order, original order #%lld [%d]", login, order->Order(), ret);
|
|
|
@@ -306,15 +330,18 @@ void CPluginInstance::OnOrderDelete(const IMTOrder * order)
|
|
|
int direction = 1;
|
|
|
if (order->Type() == IMTOrder::OP_SELL)
|
|
|
direction = -1;
|
|
|
- context.volume += direction * order->VolumeInitial();
|
|
|
+ context.volume += direction * order->VolumeInitial();
|
|
|
|
|
|
- auto wfut = m_redis_client->hset(order_buf, login_buf, std::string((char*)&context, sizeof(context)));
|
|
|
- m_redis_client->sync_commit();
|
|
|
- auto wrep = fut.get();
|
|
|
- if (wrep.ko())
|
|
|
+ m_api->LoggerOut(MTLogOK, L"write cache, key %s, field %s", s2ws(order_buf).c_str(), s2ws(login_buf).c_str());
|
|
|
+
|
|
|
+ m_redis_client->hset(order_buf, login_buf, std::string((char*)&context, sizeof(position_context)), [this](cpp_redis::reply& r)
|
|
|
{
|
|
|
- // FIXME: 错误处理
|
|
|
- }
|
|
|
+ if (r.ko())
|
|
|
+ {
|
|
|
+ m_api->LoggerOut(MTLogErr, L"redis: %s", r.error().c_str());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ m_redis_client->commit();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -393,12 +420,12 @@ void CPluginInstance::OnDealPerform(const IMTDeal * deal, IMTAccount * account,
|
|
|
|
|
|
// FIXME: 需要检查现在的deal是否和之前的order对应。如果没有记录到,则没法根本无法正常跟单以及平仓
|
|
|
char order_buf[128];
|
|
|
- sprintf(order_buf, "%lld", deal->Order());
|
|
|
+ sprintf(order_buf, "%lld", deal->PositionID());
|
|
|
IMTDeal* new_deal = m_api->DealCreate();
|
|
|
|
|
|
std::vector<std::string>* fields = nullptr;
|
|
|
|
|
|
- ScopeGuard guard([new_deal, fields]
|
|
|
+ ScopeGuard guard([new_deal, &fields]
|
|
|
{
|
|
|
new_deal->Release();
|
|
|
if (fields)
|
|
|
@@ -412,6 +439,18 @@ void CPluginInstance::OnDealPerform(const IMTDeal * deal, IMTAccount * account,
|
|
|
char login_buf[128];
|
|
|
for (auto login : m_followers)
|
|
|
{
|
|
|
+ ScopeGuard g([position, &fields, this, login, login_buf]()
|
|
|
+ {
|
|
|
+ if (position->Volume() == 0)
|
|
|
+ {
|
|
|
+ if (fields == nullptr)
|
|
|
+ fields = new(std::vector<std::string>);
|
|
|
+
|
|
|
+ m_api->LoggerOut(MTLogOK, L"add field %lld to be delete", login);
|
|
|
+ fields->push_back(login_buf);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
sprintf(login_buf, "%lld", login);
|
|
|
auto fut = m_redis_client->hget(order_buf, login_buf);
|
|
|
m_redis_client->sync_commit();
|
|
|
@@ -442,12 +481,17 @@ void CPluginInstance::OnDealPerform(const IMTDeal * deal, IMTAccount * account,
|
|
|
double storage = deal->Storage() * prop;
|
|
|
double raw_profit = deal->ProfitRaw() * prop;
|
|
|
|
|
|
+ m_api->LoggerOut(MTLogOK, L"add new deal, volume %lld, volume closed %lld, order #%lld, position #%lld", volume, volume_closed, context.cur_ord, context.position_id);
|
|
|
+
|
|
|
new_deal->Clear();
|
|
|
+ new_deal->Assign(deal);
|
|
|
+
|
|
|
+ new_deal->Login(login);
|
|
|
new_deal->DealSet(0);
|
|
|
new_deal->Volume(volume);
|
|
|
new_deal->VolumeExt(volume_ext);
|
|
|
new_deal->VolumeClosed(volume_closed);
|
|
|
- new_deal->VolumeClosedExt();
|
|
|
+ new_deal->VolumeClosedExt(volume_closed_ext);
|
|
|
new_deal->ProfitRaw(raw_profit);
|
|
|
new_deal->Profit(profit);
|
|
|
new_deal->Commission(commission);
|
|
|
@@ -459,33 +503,34 @@ void CPluginInstance::OnDealPerform(const IMTDeal * deal, IMTAccount * account,
|
|
|
if (ret != MT_RET_OK)
|
|
|
{
|
|
|
// TODO: 有没有更多的错误处理?
|
|
|
- m_api->LoggerOut(MTLogErr, L"%lld cannot add deal [%d], original deal: #%lld", login, ret, deal->Deal());
|
|
|
+ m_api->LoggerOut(MTLogErr, L"%lld cannot add deal [%d] to order #%lld, original deal: #%lld", login, ret, context.cur_ord, deal->Deal());
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- m_api->LoggerOut(MTLogOK, L"add deal #%lld, original deal #%lld [%d]", new_deal->Deal(), deal->Deal());
|
|
|
-
|
|
|
- if (position->Volume() == 0)
|
|
|
- {
|
|
|
- if (fields == nullptr)
|
|
|
- fields = new(std::vector<std::string>);
|
|
|
-
|
|
|
- fields->push_back(login_buf);
|
|
|
- }
|
|
|
+ m_api->LoggerOut(MTLogOK, L"add deal #%lld, original deal #%lld", new_deal->Deal(), deal->Deal());
|
|
|
}
|
|
|
|
|
|
+ m_api->LoggerOut(MTLogOK, L"deal #%lld, position #%lld, volume %lld", deal->Deal(), position->Position(), position->Volume());
|
|
|
if (position->Volume() == 0)
|
|
|
{
|
|
|
// 如果平仓,则删除hash值
|
|
|
- if (position->Volume() == 0)
|
|
|
+ if (position->Volume() == 0 && fields != nullptr)
|
|
|
{
|
|
|
- auto fut = m_redis_client->hdel(order_buf, *fields);
|
|
|
- m_redis_client->sync_commit();
|
|
|
- auto rep = fut.get();
|
|
|
- if (rep.ko())
|
|
|
+ m_redis_client->hdel(order_buf, *fields, [this](cpp_redis::reply& r)
|
|
|
{
|
|
|
- // TODO 错误处理
|
|
|
- }
|
|
|
+ if (r.ko())
|
|
|
+ {
|
|
|
+ // TODO 错误处理
|
|
|
+ try
|
|
|
+ {
|
|
|
+ m_api->LoggerOut(MTLogErr, L"redis: %s", r.error().c_str());
|
|
|
+ }
|
|
|
+ catch (...)
|
|
|
+ {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ m_redis_client->commit();
|
|
|
}
|
|
|
|
|
|
// TODO 当position中的volume为0时,持仓被彻底平调,被跟订单是否也该检查
|