/// <summary>
        /// 1)Triggers recalculation of bot positions
        /// 2)Trigger update bot positions on GUI
        ///
        /// Call when bid and ask ins stock changed
        ///
        /// Call from:
        ///
        /// Plaza2Connector\CStockConverterP2.ThreadStockConverter
        /// ASTS\CStockCOnverterASTS.ProcessConvert
        /// </summary>
        /// <param name="instrument"></param>
        public void RefreshBotPos(string instrument)
        {
            if (!UserDealsPosBoxClient.IsReadyRefreshBotPos())
            {
                return;
            }

            lock (LckDictPositionsOfBots)
            {
                try
                {
                    foreach (KeyValuePair <int, Dictionary <string, CBotPos> > kvp in DictPositionsOfBots)
                    {
                        int botId = kvp.Key;

                        if (kvp.Value.ContainsKey(instrument))
                        {
                            CBotPos bp = kvp.Value[instrument];

                            bp.CalcCurrentPos();
                            UserDealsPosBoxClient.GUIBotUpdateMonitorPos(bp, instrument, botId);
                        }
                    }
                }

                catch (Exception e)
                {
                    Error("RefreshBotPos", e);
                }
            }
        }
        /// <summary>
        ///  Calculate bot position when new deal was recieved  from server.
        ///
        ///  Call from:
        ///  UserDealsPosBox.Update
        ///
        /// </summary>
        /// <param name="rd"></param>
        /// <param name="isOnlineASTSCalc">Special case - only for ASTS and for online</param>
        public virtual void CalculateBotsPos(CRawUserDeal rd, bool isOnlineASTSCalc = false)
        {
            lock (LckDictPositionsOfBots)
            {
                //TODO: check and remove mutex
                //  mxDictPositionRecord.WaitOne();
                try
                {
                    string instrument = rd.Instrument; //UserDealsPosBoxClient.GetTicker(rd.Isin_Id);


                    //if deals was already processed  (not seen yet) - move to Deals Log
                    if (IsNeedUpdateUserDealsLog(rd, LatestDealsData))
                    {
                        UpdateDealsData(instrument, rd);
                    }



                    //if data was already processed return
                    if (!IsNeedProcessPos(rd, LatestBotPosData, isOnlineASTSCalc))
                    {
                        return;
                    }



                    int extID = (int)((rd.Ext_id_buy != 0) ? rd.Ext_id_buy : rd.Ext_id_sell);


                    CBotPos BotPos = GetBotPos(extID, instrument);


                    BotPos.OldAmount = BotPos.Amount;

                    //increase or decrease position
                    //amount depend on direction
                    //position amount has a sign
                    if (rd.Ext_id_buy != 0)
                    {
                        BotPos.Amount += rd.Amount;
                    }
                    else if (rd.Ext_id_sell != 0)
                    {
                        BotPos.Amount -= rd.Amount;
                    }



                    //  1)New position opened
                    //  2)Deal has the same dir as already opened pos - increase pos
                    if ((BotPos.OldAmount >= 0 && rd.Ext_id_buy != 0) || (BotPos.OldAmount <= 0 && rd.Ext_id_sell != 0))
                    {
                        //new position was opened
                        if (BotPos.OldAmount == 0)
                        {
                            BotPos.OnOpenNewPos(rd);
                        }


                        //2018-06-07 was before OnOpenNewPos
                        BotPos.AddOpenedCostHist(rd.Id_Deal, rd.Price, rd.Amount,
                                                 rd.Fee_buy + rd.Fee_sell, rd.Fee_Dealing, rd.FeeStock,
                                                 (EnmDealDir)rd.Dir, rd.Moment, rd.ReplId);


                        BotPos.CalcCurrentPos();

                        //UpdateLatestBotPos(extID, instrument, BotPos);
                    }
                    //deal has another dir than opened pos
                    else if ((BotPos.OldAmount >= 0 && rd.Ext_id_sell != 0) || (BotPos.OldAmount <= 0 && rd.Ext_id_buy != 0))
                    {
                        //new deal has another direction and amount less (or equal) than current position
                        //if we fully close or partial close no matter -
                        //using Close method calculation of profit
                        if (Math.Abs(rd.Amount) <= Math.Abs(BotPos.OldAmount))
                        {
                            BotPos.AddClosedCostHist(rd.Id_Deal, rd.Price, Math.Abs(rd.Amount),
                                                     rd.Fee_buy + rd.Fee_sell, rd.Fee_Dealing, rd.FeeStock,
                                                     (EnmDealDir)rd.Dir, rd.Moment, rd.ReplId);


                            BotPos.Close(rd.Moment, rd.ReplId);



                            //Amount after a new deal is empty. Position was fully closed.
                            //The simpliest case
                            if (BotPos.Amount == 0)
                            {
                                //BotPos.CloseReduse();
                                UpdateLatestBotPos(extID, instrument, BotPos);
                                UpdateUserPosLog(extID, instrument, BotPos, rd);

                                BotPos = new CBotPos(instrument, this, AcconuntsFeeProc[extID]);
                            }
                        }
                        //new deal has another direction and amount more than current position
                        //so, we need revert position
                        //first close previous direction pos than open another dir pos
                        //with remain
                        else if ((Math.Abs(rd.Amount) > Math.Abs(BotPos.OldAmount)))
                        {
                            //note: using old amount for fully close
                            BotPos.AddClosedCostHist(rd.Id_Deal, rd.Price, Math.Abs(BotPos.OldAmount),
                                                     rd.Fee_buy + rd.Fee_sell, rd.Fee_Dealing, rd.FeeStock,
                                                     (EnmDealDir)rd.Dir,
                                                     rd.Moment, rd.ReplId);

                            decimal amountRamained = BotPos.Mult * (Math.Abs(BotPos.OldAmount) - Math.Abs(rd.Amount));

                            BotPos.Close(rd.Moment, rd.ReplId);

                            UpdateLatestBotPos(extID, instrument, BotPos);
                            UpdateUserPosLog(extID, instrument, BotPos, rd);

                            BotPos        = new CBotPos(instrument, this, AcconuntsFeeProc[extID]);
                            BotPos.Amount = amountRamained;


                            BotPos.OnOpenNewPos(rd);

                            //2018-06-07 was before OnOpenNewPos
                            BotPos.AddOpenedCostHist(rd.Id_Deal, rd.Price, Math.Abs(amountRamained),
                                                     rd.Fee_buy + rd.Fee_sell, rd.Fee_Dealing, rd.FeeStock,
                                                     (EnmDealDir)rd.Dir, rd.Moment,
                                                     rd.ReplId);

                            BotPos.CalcCurrentPos();
                        }
                    }
                    //Update positions of all bots of all instruments
                    DictPositionsOfBots[extID][instrument] = BotPos;

                    UserDealsPosBoxClient.TriggerRecalculateBot(extID, instrument, EnmBotEventCode.OnUserDeal, (CBotPos)BotPos.Copy());

                    _client.UpdDBPosInstr(extID, rd.Instrument, BotPos.Amount, BotPos.AvPos);
                }
                catch (Exception e)
                {
                    Error("CuserDealsBox.CalculateBotsPos", e);
                }

                //   mxDictPositionRecord.ReleaseMutex();
            }//end of  lock (LckDictPositionsOfBots)

            // LckDictPositionsOfBots.ReleaseMutex();
        }