/// <summary> /// Call when: /// /// Trade update message triggered. Possible two cases: /// /// 1) When we've not recieved trade execute message - do full update /// 2) When we already recieved Trade execute message (TE) - just update fee /// /// Call from: /// /// CBitfinexWeebSockConnector.ProcessUserTradeUpdate /// /// /// </summary> /// <param name="rt"></param> public void UpdateUserDealsLateUpd(ResponseTrades rt) { Log("[UpdateUserDealsLateUpd] " + rt.ToString()); EnmOrderDir dir = rt.ExecAmount > 0 ? EnmOrderDir.Buy : EnmOrderDir.Sell; //TODO change to deal dir EnmDealDir dealDir = rt.ExecAmount > 0 ? EnmDealDir.Buy : EnmDealDir.Sell; //TODO change to deal dir string instrument = rt.Pair.Remove(0, 1); //remove 't' decimal dcmlAmount = Convert.ToDecimal(rt.ExecAmount); DateTime moment = CUtilTime.DateTimeFromUnixTimestampMillis(rt.MtsCreate); int botId = _userOrderBoxCrypto.GetBotIdOfOrder(instrument, rt.OrderId); //fee recieved no worry about "no fee" deals if (rt.Fee != 0) { lock (_lstDealsWithNoFee) { _lstDealsWithNoFee.RemoveAll(el => el.Id == rt.Id); } } //if deal is not processed by "trade execute message" yet - //do full update. bool bNotProcessedYet = (_lstNotProcessedDeals.Find(el => el.Id == rt.Id) != null); //Deal was not processed yet - do full update if (bNotProcessedYet) { if (botId > 0) //botId found { Log("[UpdateUserDealsLateUpd]. First processing deal. botId=" + botId); _userDealsPosBoxCrypto.Update(rt.Id, rt.OrderId, instrument, dir, dcmlAmount, botId, Convert.ToDecimal(rt.ExecPrice), moment, rt.MtsCreate, (decimal)rt.Fee); //deal processed no need update it - do remove _lstNotProcessedDeals.RemoveAll(el => el.Id == rt.Id); } else //botId not found - now having a REAL problem { Error("CAUTION ! UpdateUserDealsLateUpd. BotId not found !"); //2018-05-14 remember deals with no botId for future processing //2018-05-24 refact to funct AddDealNoBotId(rt); } } //if deal has already processed by "trade execute message" just update fee data else { Log("[UpdateUserDealsLateUpd] Update fee"); _userDealsPosBoxCrypto.UpdateFee(botId, instrument, rt.Id, Math.Abs(Convert.ToDecimal(rt.Fee)), dealDir ); //TODO update fee if order if not found } }
/// <summary> /// Late updates fee data of BotPos. Deals data (id, price etc) /// was already saved before to specific lists of CPosChangeFrag structs: /// ListOpeningPosChanges and ListClosingPosChanges /// So we need to find CPosChangeFrag element with DealId and update /// it's fee. /// Could be three cases: /// 1) If BotPos is opened (is not fully closed yet) than update fee of DictPositionsOfBots /// element. /// 2) If BotPot was fully closed than update fee of DicBotPosLog /// 3) If position "rotated". For that case, if botpos is opening, /// we check last DicBotPosLog element and if IsFeeLateCalced is not set /// we perform recalc fee for this element. Note: fee of rotating deal /// adds to the new "opened" position. /// /// If position was fully closed or rotated, saved to DicBotPosLog and all fees are /// not zeroes do update BotPos fee, and update other systems(Database, bots, etc) /// /// 2018-06-16 - as could be two deals with the same DealId (cross situation) /// do check DealId and Dir now. /// /// Call from: /// 1) CryptoDealingServer.UpdateUserDealsLateUpd /// 2) UserDealsPosBoxCrypto.Update /// </summary> /// <param name="botId"></param> /// <param name="instrument"></param> /// <param name="dealId"></param> /// <param name="fee"></param> public void UpdateFee(int botId, string instrument, long dealId, decimal fee, EnmDealDir dir) { bool bDealWithNoFee = false; bool bFoundInPosLog = false; bool bFoundInOpenedPos = false; bool bFoundHistNotFeeCalced = false; bool bNullAnomalyFound = false; CBotPos bpClosed = null; decimal calcedFee = 0; decimal feeDealing = 0; decimal feeStock = 0; decimal calcedFeeForPos = 0; decimal feeDealingForPos = 0; decimal feeStockForPos = 0; Log(String.Format("[UpdateFee] botId={0} instrument={1} dealId={2} fee={3}", botId, instrument, dealId, fee)); //first find in opened positions lock (LckDictPositionsOfBots) { if (DictPositionsOfBots.ContainsKey(botId)) { if (DictPositionsOfBots[botId].ContainsKey(instrument)) { CBotPos bp = DictPositionsOfBots[botId][instrument]; foreach (var el in bp.ListOpeningPosChanges) { if (el.IdDeal == dealId && el.Dir == dir) //2018-06-16 check dir { //2018-06-07 protect against override fee with wrong "0" value if (fee == 0 && el.Fee != 0) { Log("Protect to owerrite with zero. ListOpeningPosChanges"); } else { Log("Deals of DictPositionsOfBot's opening positions. Do Update fee."); //2018-07-19 //2018-08-03 removed check // if (el.Fee == 0) CalculateFees(botId, fee, ref calcedFee, ref feeDealing, ref feeStock, el); bFoundInOpenedPos = true; } //return; //2018-05-23 removed } } foreach (var el in bp.ListClosingPosChanges) { if (el.IdDeal == dealId && el.Dir == dir) //2018-06-16 check dir { //2018-06-07 protect against override fee with wrong "0" value if (fee == 0 && el.Fee != 0) { Log("Protect to owerrite with zero. ListClosingPosChanges"); } else { Log("Deals of DictPositionsOfBot's closing positions. Do Update fee."); //2018-07-19 //2018-08-03 removed check //if (el.FeeDealing == 0) CalculateFees(botId, fee, ref calcedFee, ref feeDealing, ref feeStock, el); bFoundInOpenedPos = true; } //return; //2018-05-23 removed } } } } } //then look in historical positions lock (DicBotPosLog) { //if not found in opened pos find in poslog if (!bFoundInOpenedPos) { if (DicBotPosLog.ContainsKey(botId)) { if (DicBotPosLog[botId].ContainsKey(instrument)) { if (DicBotPosLog[botId][instrument].Count > 0) { bpClosed = DicBotPosLog[botId][instrument].Last(); foreach (var el in bpClosed.ListClosingPosChanges) { if (el.IdDeal == dealId && el.Dir == dir) //2018-06-16 check dir { //TODO normal loading from DB after disconnect //2018-07-19 // //2018-08-03 removed check //if (el.FeeDealing == 0) CalculateFees(botId, fee, ref calcedFee, ref feeDealing, ref feeStock, el); bFoundInPosLog = true; Log("bFoundInPosLog"); } else if (el.Fee == 0) { bDealWithNoFee = true; Log(String.Format("bDealWithNoFee DealId={0}", el.IdDeal)); } } } } } } //2018-05-23 check if last pos "fee processed". //This is for processing "rotate" position case if (bFoundInOpenedPos) { if (DicBotPosLog.ContainsKey(botId)) { if (DicBotPosLog[botId].ContainsKey(instrument)) { if (DicBotPosLog[botId][instrument].Count > 0) { bpClosed = DicBotPosLog[botId][instrument].Last(); if (bpClosed != null) { if (bpClosed.IsFeeLateCalced == 0) { bFoundHistNotFeeCalced = true; Log("bFoundHistNotFeeCalced"); } } } } } } //2018-06-03 protect against bpClosed==null "anlomaly" if (bFoundInPosLog && bpClosed == null) { bpClosed = DicBotPosLog[botId][instrument].Last(); bNullAnomalyFound = true; Log("Null anomaly found"); } //end protect amomaly //TODO check if fee not recalc yet //if all deals of historical postions are closed, all fees are saved (no bDealWithNoFee) // perform recalc and set botpos as fee calculated. //2018-05-23 also perform calc when "rotate pos" situation (bFoundHistNotFeeCalced) //2018-06-20 try to remove bDealWithNoFee and IsFeeLateCalced condition becaused //fee COULD BE zero in a "very little" amount case. Note: as we check "bpClosed!=null" //we calcuylate and update total position fee after position close. if (bpClosed != null) { if (/*bpClosed.IsFeeLateCalced==0 &&*/ (bFoundInPosLog || bFoundHistNotFeeCalced) /*&& !bDealWithNoFee*/) { Log("Update fee of historical position"); if (bpClosed.ListOpeningPosChanges != null) //2018-07-19 protect against null data (when loaded from DB to poslog) { bpClosed.ListOpeningPosChanges.ForEach(el => { calcedFeeForPos += el.Fee; feeStockForPos += el.Fee_Stock; feeDealingForPos += el.FeeDealing; } ); } if (bpClosed.ListClosingPosChanges != null) //2018-07-19 protect against null data (when loaded from DB to poslog) { bpClosed.ListClosingPosChanges.ForEach(el => { calcedFeeForPos += el.Fee; feeStockForPos += el.Fee_Stock; feeDealingForPos += el.FeeDealing; } ); } if (calcedFeeForPos != 0) //2018-07-19 protect against owerride fee (if null we do not need) { bpClosed.Fee_Stock = feeStockForPos;; //fee recieved from stock bpClosed.FeeDealing = feeDealingForPos; //fee by dealing bpClosed.Fee = calcedFeeForPos; // 2018-07-19 bpClosed.Fee_Total = bpClosed.Fee; //is equal fee bpClosed.VMClosed_RUB_stock = bpClosed.VMClosed_RUB_clean - bpClosed.Fee_Stock; //is equal VM on stock exchange (for checking), substract only stock fee bpClosed.VMClosed_RUB = bpClosed.VMClosed_RUB_clean - bpClosed.Fee; //resulting VM substract full fee bpClosed.VMClosed_RUB_user = bpClosed.VMClosed_RUB; //is equal VMClosed_RUB bpClosed.IsFeeLateCalced = 1; _client.UpdateUserPosLogLate(new CDBUpdateLate { Instrument = instrument, ReplId = bpClosed.ReplIdClosed, BotId = botId, Fee_Total = bpClosed.Fee_Total, Fee = bpClosed.Fee, Fee_Stock = bpClosed.Fee_Stock, FeeDealing = bpClosed.FeeDealing, VMClosed_RUB = bpClosed.VMClosed_RUB, VMClosed_RUB_user = bpClosed.VMClosed_RUB_user, VMClosed_RUB_stock = bpClosed.VMClosed_RUB_stock, IsFeeLateCalced = bpClosed.IsFeeLateCalced }); } } } //===================== DEBUGGING START //2018-06-03 this is for debugging //to catch bpClosed==null situation if (bFoundInPosLog) { if (bpClosed == null || bNullAnomalyFound) { Log("bpClosed == null catching situation"); if (DicBotPosLog.ContainsKey(botId)) { if (DicBotPosLog[botId].ContainsKey(instrument)) { if (DicBotPosLog[botId][instrument].Count != 0) { var lastEl = DicBotPosLog[botId][instrument].Last(); if (lastEl == null) { Log("Last el is null"); } foreach (var elBp in DicBotPosLog[botId][instrument]) { Log(String.Format("DtOpen={0} DtClosed={1} BuySell={2} " + "CloseAmount={3} Priceopen={4} Priceopen={4} PriceClose={5}", elBp.DtOpen, elBp.DtClose, elBp.BuySell, elBp.CloseAmount, elBp.PriceOpen, elBp.PriceClose)); } } else { Log("Count is 0"); } } else { Log("Doesn't contain instrument"); } } else { Log("Doesn't contain botId"); } } } //DEBUGGING END } //end lock (DicBotPosLog) _client.TriggerRecalculateBot(botId, "", EnmBotEventCode.OnForceUpdTotalVM, null); _client.UpdateFeeUserDealsLog(new CDBUpdateFeeUserDealsLog { DealId = dealId, Fee = calcedFee, FeeDealing = feeDealing, FeeStock = feeStock }); // }
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { EnmDealDir dVal = (EnmDealDir)value; return(dVal == EnmDealDir.Buy ? true : false); }
/// <summary> /// Add new "position change" fragment to closed list. /// 2018-03-11 added idDeal /// </summary> public void AddClosedCostHist(long idDeal, decimal price, decimal amount, decimal fee, decimal feeDealing, decimal feeStock, EnmDealDir dir, DateTime moment, long replId) { long bpDtOpenTimeStampMs = CUtilTime.GetUnixTimestampMillis(DtOpen); //TODO check add fee ? ListClosingPosChanges.Add(new CPosChangeFrag { IdDeal = idDeal, Dir = dir, Moment = moment, ReplId = replId, Price = price, Amount = amount, Fee = fee, FeeDealing = feeDealing, Fee_Stock = feeStock, BP_DtOpen_timestamp_ms = bpDtOpenTimeStampMs }); m_userDealsPosBox.BindDealBotPos(idDeal, bpDtOpenTimeStampMs); }
public void TestDealStruct(CDealClass dc, int amount, EnmDealDir dirDeal, decimal price) { Assert.AreEqual(amount, dc.Amount); Assert.AreEqual(dirDeal, dc.DirDeal); Assert.AreEqual(price, dc.Price); }
/// <summary> /// Update deal's history log /// </summary> /// <param name="instrument"></param> /// <param name="rd"></param> private void UpdateDealsData(string instrument, CRawUserDeal rd) { CUserDeal userDeal = null; long timeMili = 0; CUserDeal dealWithSameId = null; int botId = (int)(rd.Ext_id_buy > 0 ? rd.Ext_id_buy : rd.Ext_id_sell); lock (DictUserDealsLog) { if (!DictUserDealsLog.ContainsKey(botId)) { DictUserDealsLog[botId] = new Dictionary <string, List <CUserDeal> >(); } if (!DictUserDealsLog[botId].ContainsKey(instrument)) { DictUserDealsLog[botId][instrument] = new List <CUserDeal>(); } dealWithSameId = DictUserDealsLog[botId][instrument].FirstOrDefault(a => a.ReplId == rd.ReplId); //deal doesn't have the same id if (dealWithSameId == null) { EnmDealDir dd = rd.Ext_id_buy > 0 ? EnmDealDir.Buy : EnmDealDir.Sell; userDeal = new CUserDeal { ReplId = rd.ReplId, Amount = rd.Amount, Moment = rd.Moment, Price = rd.Price, BuySell = dd, Fee = rd.Fee_buy + rd.Fee_sell, DealId = rd.Id_Deal //2018-06-13 }; DictUserDealsLog[botId][instrument].Add((CUserDeal)userDeal); // Plaza2Connector.TriggerRecalculateBot(botId, EnmBotEventCode.OnUserDeal, timeMili = CUtilTime.GetUnixTimestampMillis(userDeal.Moment); LatestDealsData.Update(botId, instrument, new CLatestTradeData { Dt_timestamp_ms = timeMili, ReplId = rd.ReplId, Dt = rd.Moment } ); CDBUserDeal dbUSerDeal = new CDBUserDeal(); CUtil.CopyObjProperties(userDeal, dbUSerDeal); dbUSerDeal.Instrument = instrument; dbUSerDeal.account_trade_Id = (int)botId; dbUSerDeal.stock_exch_id = UserDealsPosBoxClient.StockExchId; //StockExchangeId; dbUSerDeal.ReplId = rd.ReplId; dbUSerDeal.DealId = rd.Id_Deal; //2018-05-31 dbUSerDeal.Fee = rd.Fee_buy + rd.Fee_sell; //2018-05-31 UserDealsPosBoxClient.UpdateDBUserDealsLog(dbUSerDeal); } } }