Переглянути джерело

修复bug;order add和update都无法将订单改为filled,改为使用history add来增加订单,但是目前在admin中平仓的deal未完全匹配到该position,另外该方式不会产生持仓,还需要fixbalance来修复balance

KarsusNeko 6 роки тому
батько
коміт
3ab8eb2aca
1 змінених файлів з 114 додано та 69 видалено
  1. 114 69
      MT5MonkPAMM/PluginInstance.cpp

+ 114 - 69
MT5MonkPAMM/PluginInstance.cpp

@@ -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时,持仓被彻底平调,被跟订单是否也该检查