private void InteractiveSplineOnClickEvent(object sender, InteractiveActionEventArgs eventArgs) { PositionsManager posMan = PositionsManager.GetManager(m_context); if (posMan.BlockTrading) { //string msg = String.Format("[{0}] Trading is blocked. Please, change 'Block Trading' parameter.", m_optionPxMode); string msg = RM.GetStringFormat("OptHandlerMsg.PositionsManager.TradingBlocked", m_optionPxMode); m_context.Log(msg, MessageType.Info, true); return; } SmileNodeInfo nodeInfo = eventArgs.Point.Tag as SmileNodeInfo; if (nodeInfo == null) { //string msg = String.Format("[{0}] There is no nodeInfo. Quote type: {1}; Strike: {2}", m_optionPxMode); string msg = RM.GetStringFormat(CultureInfo.InvariantCulture, "OptHandlerMsg.ThereIsNoNodeInfo", m_context.Runtime.TradeName, m_optionPxMode, eventArgs.Point.ValueX); m_context.Log(msg, MessageType.Error, true); return; } nodeInfo.Qty = m_qty; nodeInfo.ClickTime = DateTime.Now; // Передаю событие в PositionsManager дополнив его инфой о количестве лотов posMan.InteractiveSplineOnClickEvent(m_context, sender, eventArgs); }
private void res_EndDragEvent(object sender, InteractiveActionEventArgs e) { InteractiveSeries oldLine = sender as InteractiveSeries; if (oldLine != null) { //SmileInfo info = oldLine.GetTag<SmileInfo>(); //if (info != null) //{ // List<double> xs = new List<double>(); // List<double> ys = new List<double>(); // foreach (InteractiveObject oldObj in oldLine.ControlPoints) // { // if (!(oldObj.Anchor.IsVisible ?? oldObj.AnchorGraphPointData.IsVisible)) // continue; // double k = oldObj.Anchor.ValueX; // double sigma = oldObj.Anchor.ValueY; // xs.Add(k); // ys.Add(sigma); // } // try // { // NotAKnotCubicSpline spline = new NotAKnotCubicSpline(xs, ys); // info.ContinuousFunction = spline; // info.ContinuousFunctionD1 = spline.DeriveD1(); // oldLine.Tag = info; // } // catch (Exception ex) // { // m_context.Log(ex.ToString(), MessageType.Error, true); // //return Constants.EmptySeries; // } //} // Сразу отписываюсь! oldLine.EndDragEvent -= res_EndDragEvent; } m_context.Recalc(); }
private void InteractiveSplineOnClickEvent(object sender, InteractiveActionEventArgs eventArgs) { OptionPxMode pxMode = m_isLong ? OptionPxMode.Ask : OptionPxMode.Bid; PositionsManager posMan = PositionsManager.GetManager(m_context); // Из практики торговли часто бывает ситуация, что торговля заблокирована, а снять задачу котирования УЖЕ хочется. //if (posMan.BlockTrading) //{ // //string msg = String.Format("[{0}] Trading is blocked. Please, change 'Block Trading' parameter.", m_optionPxMode); // string msg = String.Format(RM.GetString("OptHandlerMsg.PositionsManager.TradingBlocked"), pxMode); // m_context.Log(msg, MessageType.Info, true); // return; //} InteractivePointActive tmp = eventArgs.Point; if ((tmp.Tag == null) || (!(tmp.Tag is PositionsManager.IvTargetInfo))) { string msg = String.Format("[{0}.ClickEvent] Denied #1", GetType().Name); m_context.Log(msg, MessageType.Warning, false); return; } { string msg = String.Format(CultureInfo.InvariantCulture, "[{0}.ClickEvent] Strike: {1}", GetType().Name, eventArgs.Point.ValueX); m_context.Log(msg, MessageType.Warning, false); } var ivTarget = tmp.Tag as PositionsManager.IvTargetInfo; // Передаю событие в PositionsManager //posMan.InteractiveSplineOnQuoteIvEvent(m_context, sender, eventArgs); // ОЧЕНЬ БОЛЬШОЙ ВОПРОС ЧТО БУДЕТ С КОНТЕКСТОМ ПРИ ЭТОМ??? int res = posMan.CancelVolatility(m_context, ivTarget, "Left-click"); if (res > 0) { string msg = String.Format(RM.GetString("OptHandlerMsg.PositionsManager.IvTargetCancelled"), pxMode, ivTarget); m_context.Log(msg, MessageType.Info, true, new Dictionary <string, object> { { "VOLATILITY_ORDER_CANCELLED", msg } }); // Вызываем принудительный пересчет агента, чтобы немедленно убрать заявку из стакана m_context.Recalc(); } }
private void InteractiveSplineOnClickEvent(object sender, InteractiveActionEventArgs eventArgs) { PositionsManager posMan = PositionsManager.GetManager(m_context); if (posMan.BlockTrading) { //string msg = String.Format("[{0}] Trading is blocked. Please, change 'Block Trading' parameter.", m_optionPxMode); string msg = RM.GetStringFormat("OptHandlerMsg.PositionsManager.TradingBlocked", m_optionPxMode); m_context.Log(msg, MessageType.Warning, true); return; } List <InteractiveActionEventArgs> onClickEvents = m_context.LoadObject(VariableId + "OnClickEvent") as List <InteractiveActionEventArgs>; if (onClickEvents == null) { onClickEvents = new List <InteractiveActionEventArgs>(); m_context.StoreObject(VariableId + "OnClickEvent", onClickEvents); } onClickEvents.Add(eventArgs); m_context.Recalc(RecalcReasons.ChartTrading, null); }
private void InteractiveSplineOnQuoteIvEvent(object sender, InteractiveActionEventArgs eventArgs) { OptionPxMode pxMode = (m_qty > 0) ? OptionPxMode.Ask : OptionPxMode.Bid; PositionsManager posMan = PositionsManager.GetManager(m_context); if (posMan.BlockTrading) { //string msg = String.Format("[{0}] Trading is blocked. Please, change 'Block Trading' parameter.", m_optionPxMode); string msg = RM.GetStringFormat("OptHandlerMsg.PositionsManager.TradingBlocked", pxMode); m_context.Log(msg, MessageType.Info, true); return; } InteractivePointActive tmp = eventArgs.Point; if ((tmp == null) || (tmp.IsActive == null) || (!tmp.IsActive.Value) || DoubleUtil.IsZero(m_qty)) { //string msg = String.Format("[{0}] Unable to get direction of the order. Qty:{1}", pxMode, m_qty); string msg = RM.GetStringFormat("OptHandlerMsg.PositionsManager.UndefinedOrderDirection", pxMode, m_qty); m_context.Log(msg, MessageType.Error, true); return; } SmileNodeInfo nodeInfo = tmp.Tag as SmileNodeInfo; if (nodeInfo == null) { //string msg = String.Format("[{0}] There is no nodeInfo. Quote type: {1}; Strike: {2}", pxMode); string msg = RM.GetStringFormat(CultureInfo.InvariantCulture, "OptHandlerMsg.ThereIsNoNodeInfo", m_context.Runtime.TradeName, pxMode, eventArgs.Point.ValueX); m_context.Log(msg, MessageType.Error, true); return; } { string msg = String.Format(CultureInfo.InvariantCulture, "[{0}.ClickEvent] Strike: {1}", GetType().Name, tmp.ValueX); m_context.Log(msg, MessageType.Info, false); } nodeInfo.OptPx = m_shiftIv; nodeInfo.ShiftOptPx = m_shiftPriceStep; nodeInfo.ClickTime = DateTime.Now; nodeInfo.PxMode = pxMode; // [2015-10-02] Подписка на данный инструмент, чтобы он появился в коллекции Context.Runtime.Securities var candids = (from s in Context.Runtime.Securities where s.SecurityDescription.Name.Equals(nodeInfo.Symbol, StringComparison.InvariantCultureIgnoreCase) select s).ToList(); candids = (from s in candids where s.SecurityDescription.DSName.Equals(nodeInfo.DSName, StringComparison.InvariantCultureIgnoreCase) select s).ToList(); ISecurity testSec = (from s in candids let secDesc = s.SecurityDescription where secDesc.FullName.Equals(nodeInfo.FullName, StringComparison.InvariantCultureIgnoreCase) select s).SingleOrDefault(); if ((testSec == null) && (nodeInfo.Security != null)) { ISecurity sec = nodeInfo.Security; int bc = sec.Bars.Count; string msg = String.Format("[{0}] There is security DsName: {1}; Symbol: {2}; Security: {3} with {4} bars available.", pxMode, nodeInfo.DSName, nodeInfo.Symbol, nodeInfo.FullName, bc); Context.Log(msg, MessageType.Info, false); // Пересчитываю целочисленный параметр Qty в фактические лоты конкретного инструмента double actQty = Math.Abs(m_qty * sec.LotTick); // Модуль, потому что тут направление передается через PxMode nodeInfo.Qty = actQty; } else if ((nodeInfo.Pair != null) && (nodeInfo.Pair.Put != null)) { // Аварийная ветка // Пересчитываю целочисленный параметр Qty в фактические лоты конкретного инструмента double actQty = Math.Abs(m_qty * nodeInfo.Pair.Put.LotTick); // Модуль, потому что тут направление передается через PxMode nodeInfo.Qty = actQty; } else { // Аварийная ветка // Не могу пересчитать целочисленный параметр Qty в фактические лоты конкретного инструмента! //double actQty = Math.Abs(m_qty * nodeInfo.Pair.Put.LotTick); nodeInfo.Qty = Math.Abs(m_qty); // Модуль, потому что тут направление передается через PxMode string msg = String.Format(CultureInfo.InvariantCulture, "[{0}.ClickEvent] LotTick will be set to 1.", GetType().Name); m_context.Log(msg, MessageType.Warning, false); } // Не страшно, если сюда пойдет null - posMan потом сам найдет нужный опцион nodeInfo.Security = testSec; // Передаю событие в PositionsManager //posMan.InteractiveSplineOnClickEvent(m_context, sender, eventArgs); posMan.InteractiveSplineOnQuoteIvEvent(m_context, sender, eventArgs); }
private void InteractiveSplineOnClickEvent(object sender, InteractiveActionEventArgs eventArgs) { PositionsManager posMan = PositionsManager.GetManager(m_context); if (posMan.BlockTrading) { //string msg = String.Format("[{0}] Trading is blocked. Please, change 'Block Trading' parameter.", MsgId); string msg = RM.GetStringFormat("OptHandlerMsg.PositionsManager.TradingBlocked", MsgId); m_context.Log(msg, MessageType.Warning, true); return; } if (m_qty == 0) { //string msg = String.Format("[{0}] Trading is blocked for zero quantity. Qty: {1}", MsgId, qty); string msg = RM.GetStringFormat("OptHandlerMsg.PositionsManager.TradingBlockedForZeroQty", MsgId, m_qty); m_context.Log(msg, MessageType.Warning, true); return; } else if (m_qty < 0) { // GLSP-252 - Запрет на совершение сделок при отрицательном Qty //string msg = String.Format("[{0}] Trading is blocked for negative quantity. Qty: {1}", MsgId, qty); string msg = RM.GetStringFormat("OptHandlerMsg.PositionsManager.TradingBlockedForNegativeQty", MsgId, m_qty); m_context.Log(msg, MessageType.Warning, true); return; } SmileNodeInfo nodeInfo = eventArgs.Point.Tag as SmileNodeInfo; if (nodeInfo == null) { //string msg = String.Format("[{0}] There is no nodeInfo. Base asset price: {1}", MsgId); string msg = RM.GetStringFormat(CultureInfo.InvariantCulture, "OptHandlerMsg.CurrentFutPx.ThereIsNoNodeInfo", MsgId, eventArgs.Point.ValueX); m_context.Log(msg, MessageType.Error, true); return; } nodeInfo.ClickTime = DateTime.Now; // [2015-10-02] Подписка на данный инструмент, чтобы он появился в коллекции Context.Runtime.Securities ISecurity testSec = (from s in m_context.Runtime.Securities let secDesc = s.SecurityDescription where secDesc.FullName.Equals(nodeInfo.FullName, StringComparison.InvariantCultureIgnoreCase) && secDesc.DSName.Equals(nodeInfo.DSName, StringComparison.InvariantCultureIgnoreCase) && secDesc.Name.Equals(nodeInfo.Symbol, StringComparison.InvariantCultureIgnoreCase) select s).SingleOrDefault(); if (testSec == null) { ISecurity sec = nodeInfo.Security; int bc = sec.Bars.Count; string msg = String.Format("[{0}] There is security DsName: {1}; Symbol: {2}; Security: {3} with {4} bars available.", nodeInfo.PxMode, nodeInfo.DSName, nodeInfo.Symbol, nodeInfo.FullName, bc); Context.Log(msg, MessageType.Info, false); // Пересчитываю целочисленный параметр Qty в фактические лоты конкретного инструмента double actQty = m_qty * sec.LotTick; // Здесь нет модуля, потому что направление сделки несет в себе знак Qty nodeInfo.Qty = actQty; } else if ((nodeInfo.Security != null) && (nodeInfo.Security != null)) { // Аварийная ветка // Пересчитываю целочисленный параметр Qty в фактические лоты конкретного инструмента double actQty = m_qty * nodeInfo.Security.LotTick; // Здесь нет модуля, потому что направление сделки несет в себе знак Qty nodeInfo.Qty = actQty; } else { // Аварийная ветка // Не могу пересчитать целочисленный параметр Qty в фактические лоты конкретного инструмента! nodeInfo.Qty = m_qty; // Здесь нет модуля, потому что направление сделки несет в себе знак Qty string msg = String.Format(CultureInfo.InvariantCulture, "[{0}.ClickEvent] LotTick is set to 1.", GetType().Name); m_context.Log(msg, MessageType.Warning, false); } // Передаю событие в PositionsManager дополнив его инфой о количестве лотов posMan.InteractiveSplineOnClickEvent(m_context, sender, eventArgs); }
private void InteractiveSplineOnClickEvent(object sender, InteractiveActionEventArgs eventArgs) { // [2016-03-01] PROD-2452: Запрещаю торговлю по узлу, если нет "подсветки" { InteractiveObject obj = eventArgs.InteractiveObject; if ((obj == null) || (obj.Anchor == null) || (obj.ControlPoint1 == null) || (!(obj.Anchor is InteractivePointActive)) || (!(obj.ControlPoint1 is InteractivePointActive))) { string msg = String.Format("[{0}.ClickEvent] Denied #1", GetType().Name); m_context.Log(msg, MessageType.Warning, false); return; } var cp1 = (InteractivePointActive)obj.ControlPoint1; // PROD-4967 - Необязательно проверять активность якоря. // Потому что эта настройка делается на более позднем этапе в момент создания графического объекта // методом smilePanePane.AddList("SmilePane_pane_TradeAsks_chart", <...>) //var anchor = (InteractivePointActive)obj.Anchor; //if ((anchor.IsActive == null) || (!anchor.IsActive.Value) || if ((cp1.IsActive == null) || (!cp1.IsActive.Value)) { string msg = String.Format("[{0}.ClickEvent] Denied #3 (ControlPoint1 is not active)", GetType().Name); m_context.Log(msg, MessageType.Warning, false); return; } } PositionsManager posMan = PositionsManager.GetManager(m_context); if (posMan.BlockTrading) { //string msg = String.Format("[{0}] Trading is blocked. Please, change 'Block Trading' parameter.", m_optionPxMode); string msg = String.Format(RM.GetString("OptHandlerMsg.PositionsManager.TradingBlocked"), m_optionPxMode); m_context.Log(msg, MessageType.Info, true); return; } // Здесь нет проверки знака m_qty, потому что в данном кубике мы действительно можем и продавать и покупать SmileNodeInfo nodeInfo = eventArgs.Point.Tag as SmileNodeInfo; if (nodeInfo == null) { //string msg = String.Format("[{0}] There is no nodeInfo. Quote type: {1}; Strike: {2}", string msg = RM.GetStringFormat(CultureInfo.InvariantCulture, "OptHandlerMsg.ThereIsNoNodeInfo", m_context.Runtime.TradeName, m_optionPxMode, eventArgs.Point.ValueX); m_context.Log(msg, MessageType.Error, true); return; } { string msg = String.Format(CultureInfo.InvariantCulture, "[{0}.ClickEvent] Strike: {1}; Security: {2}", GetType().Name, eventArgs.Point.ValueX, nodeInfo.FullName); m_context.Log(msg, MessageType.Info, false); } nodeInfo.ClickTime = DateTime.Now; // [2015-10-02] Подписка на данный инструмент, чтобы он появился в коллекции Context.Runtime.Securities ISecurity testSec = (from s in Context.Runtime.Securities let secDesc = s.SecurityDescription where secDesc.FullName.Equals(nodeInfo.FullName, StringComparison.InvariantCultureIgnoreCase) && secDesc.DSName.Equals(nodeInfo.DSName, StringComparison.InvariantCultureIgnoreCase) && secDesc.Name.Equals(nodeInfo.Symbol, StringComparison.InvariantCultureIgnoreCase) select s).SingleOrDefault(); if (testSec == null) { ISecurity sec = nodeInfo.Security; int bc = sec.Bars.Count; string msg = String.Format("[{0}] There is security DsName: {1}; Symbol: {2}; Security: {3} with {4} bars available.", m_optionPxMode, nodeInfo.DSName, nodeInfo.Symbol, nodeInfo.FullName, bc); Context.Log(msg, MessageType.Info, false); // Пересчитываю целочисленный параметр Qty в фактические лоты конкретного инструмента double actQty = m_qty * sec.LotTick; // Здесь нет модуля, потому что направление сделки несет в себе знак Qty nodeInfo.Qty = actQty; } else if ((nodeInfo.Pair != null) && (nodeInfo.Pair.Put != null)) { // Аварийная ветка // Пересчитываю целочисленный параметр Qty в фактические лоты конкретного инструмента double actQty = m_qty * nodeInfo.Pair.Put.LotTick; // Здесь нет модуля, потому что направление сделки несет в себе знак Qty nodeInfo.Qty = actQty; } else { // Аварийная ветка // Не могу пересчитать целочисленный параметр Qty в фактические лоты конкретного инструмента! //double actQty = Math.Abs(m_qty * nodeInfo.Pair.Put.LotTick); nodeInfo.Qty = m_qty; // Здесь нет модуля, потому что направление сделки несет в себе знак Qty string msg = String.Format(CultureInfo.InvariantCulture, "[{0}.ClickEvent] LotTick is set to 1.", GetType().Name); m_context.Log(msg, MessageType.Warning, false); } // Передаю событие в PositionsManager дополнив его инфой о количестве лотов posMan.InteractiveSplineOnClickEvent(m_context, sender, eventArgs); }
private void RouteOnClickEvents(List <InteractiveActionEventArgs> eventArgs) { if (eventArgs == null) { return; } int argLen = eventArgs.Count; PositionsManager posMan = PositionsManager.GetManager(m_context); if (posMan.BlockTrading && (argLen > 0)) { eventArgs.Clear(); string msg = String.Format("[{0}] ERROR! Trading is blocked. Should NOT be here. All events were removed.", m_optionPxMode); m_context.Log(msg, MessageType.Warning, true); return; } bool recalc = false; for (int j = argLen - 1; j >= 0; j--) { InteractiveActionEventArgs eventArg = eventArgs[j]; eventArgs.RemoveAt(j); try { SmileNodeInfo nodeInfo = eventArg.Point.Tag as SmileNodeInfo; if (nodeInfo == null) { //string msg = String.Format("[{0}] There is no nodeInfo. Quote type: {1}; Strike: {2}", m_optionPxMode); string msg = RM.GetStringFormat(CultureInfo.InvariantCulture, "OptHandlerMsg.ThereIsNoNodeInfo", m_context.Runtime.TradeName, m_optionPxMode, eventArg.Point.ValueX); m_context.Log(msg, MessageType.Error, true); continue; } if ((!posMan.UseVirtualPositions) && nodeInfo.Expired) { string msg = String.Format("[{0}] Security {1} is already expired. Expiry: {2}", m_optionPxMode, nodeInfo.Symbol, nodeInfo.Security.SecurityDescription.ExpirationDate); m_context.Log(msg, MessageType.Error, true); continue; } ISecurity sec = (from s in m_context.Runtime.Securities where (s.Symbol.Equals(nodeInfo.Symbol, StringComparison.InvariantCultureIgnoreCase)) && (String.IsNullOrWhiteSpace(nodeInfo.DSName) || (s.SecurityDescription.DSName == nodeInfo.DSName)) && (String.IsNullOrWhiteSpace(nodeInfo.FullName) || (s.SecurityDescription.FullName == nodeInfo.FullName)) select s).SingleOrDefault(); if (sec == null) { string msg = String.Format("[{0}] There is no security. Symbol: {1}", m_optionPxMode, nodeInfo.Symbol); m_context.Log(msg, MessageType.Error, true); continue; } double actualPx = nodeInfo.OptPx; if (m_optionType != StrikeType.Any) { // Заменяю инструмент в соответствии с настройками кубика switch (m_optionType) { case StrikeType.Put: if (sec.SecurityDescription.ActiveType != DataSource.ActiveType.OptionPut) { var oldCall = sec; sec = nodeInfo.Pair.Put.Security; // Теперь еще нужно заменить ЦЕНУ. Проще всего это сделать через паритет. // C - P = F - K ==> P = C + K - F double putPx = nodeInfo.OptPx + nodeInfo.Strike - nodeInfo.F; // Но не меньше 1 ш.ц.! actualPx = Math.Max(putPx, sec.Tick); string txt = String.Format(CultureInfo.InvariantCulture, "[{0}] Symbol '{1}' has been replaced to '{2}' and changed price from {3} to {4}", m_optionPxMode, nodeInfo.Symbol, sec.Symbol, nodeInfo.OptPx, actualPx); m_context.Log(txt, MessageType.Warning, true); } break; case StrikeType.Call: if (sec.SecurityDescription.ActiveType != DataSource.ActiveType.OptionCall) { var oldPut = sec; sec = nodeInfo.Pair.Call.Security; // Теперь еще нужно заменить ЦЕНУ. Проще всего это сделать через паритет. // C - P = F - K ==> C = P + F - K double callPx = nodeInfo.OptPx + nodeInfo.F - nodeInfo.Strike; // Но не меньше 1 ш.ц.! actualPx = Math.Max(callPx, sec.Tick); string txt = String.Format(CultureInfo.InvariantCulture, "[{0}] Symbol '{1}' has been replaced to '{2}' and changed price from {3} to {4}", m_optionPxMode, nodeInfo.Symbol, sec.Symbol, nodeInfo.OptPx, actualPx); m_context.Log(txt, MessageType.Warning, true); } break; } } int len = sec.Bars.Count; // Валидирую наличие правильной котировки if (sec.FinInfo != null) { Debug.WriteLine("AskPx: " + sec.FinInfo.Ask); Debug.WriteLine("BidPx: " + sec.FinInfo.Bid); } recalc = true; if ((m_optionPxMode == OptionPxMode.Ask) && (m_qty > 0) || (m_optionPxMode == OptionPxMode.Bid) && (m_qty < 0)) { string signalName = "\r\nLeft-Click BUY \r\n" + eventArg.Point.Tooltip + "\r\n"; posMan.BuyAtPrice(m_context, sec, Math.Abs(m_qty), actualPx, signalName, null); } else if ((m_optionPxMode == OptionPxMode.Bid) && (m_qty > 0) || (m_optionPxMode == OptionPxMode.Ask) && (m_qty < 0)) { string signalName = "\r\nLeft-Click SELL \r\n" + eventArg.Point.Tooltip + "\r\n"; posMan.SellAtPrice(m_context, sec, Math.Abs(m_qty), actualPx, signalName, null); } else if (m_optionPxMode == OptionPxMode.Mid) { string msg = String.Format("[{0}] OptionPxMode.Mid is not implemented.", m_optionPxMode); m_context.Log(msg, MessageType.Warning, true); } else if (m_qty == 0) { string msg = String.Format("[{0}] Qty: {1}. Trading is blocked.", m_optionPxMode, m_qty); m_context.Log(msg, MessageType.Warning, true); } } catch (Exception ex) { string msg = String.Format("[{0}] {1} in RouteOnClickEvents. Message: {2}\r\n{3}", m_optionPxMode, ex.GetType().FullName, ex.Message, ex); m_context.Log(msg, MessageType.Warning, true); } } if (recalc) { m_context.Recalc(RecalcReasons.ChartTrading, null); } }
private void RouteOnClickEvents(List <InteractiveActionEventArgs> eventArgs) { if (eventArgs == null) { return; } int argLen = eventArgs.Count; PositionsManager posMan = PositionsManager.GetManager(m_context); if (posMan.BlockTrading && (argLen > 0)) { eventArgs.Clear(); string msg = String.Format("[{0}] ERROR! Trading is blocked. Should NOT be here. All events were removed.", m_optionPxMode); m_context.Log(msg, MessageType.Warning, true); return; } bool recalc = false; for (int j = argLen - 1; j >= 0; j--) { InteractiveActionEventArgs eventArg = eventArgs[j]; eventArgs.RemoveAt(j); try { SmileNodeInfo nodeInfo = eventArg.Point.Tag as SmileNodeInfo; if (nodeInfo == null) { //string msg = String.Format("[{0}] There is no nodeInfo. Quote type: {1}; Strike: {2}", m_optionPxMode); string msg = RM.GetStringFormat(CultureInfo.InvariantCulture, "OptHandlerMsg.ThereIsNoNodeInfo", m_context.Runtime.TradeName, m_optionPxMode, eventArg.Point.ValueX); m_context.Log(msg, MessageType.Error, true); continue; } if ((!posMan.UseVirtualPositions) && nodeInfo.Expired) { string msg = String.Format("[{0}] Security {1} is already expired. Expiry: {2}", m_optionPxMode, nodeInfo.Symbol, nodeInfo.Security.SecurityDescription.ExpirationDate); m_context.Log(msg, MessageType.Error, true); continue; } ISecurity sec = (from s in m_context.Runtime.Securities where (s.Symbol.Equals(nodeInfo.Symbol, StringComparison.InvariantCultureIgnoreCase)) && (String.IsNullOrWhiteSpace(nodeInfo.DSName) || (s.SecurityDescription.DSName == nodeInfo.DSName)) && (String.IsNullOrWhiteSpace(nodeInfo.FullName) || (s.SecurityDescription.FullName == nodeInfo.FullName)) select s).SingleOrDefault(); if (sec == null) { string msg = String.Format("[{0}] There is no security. Symbol: {1}", m_optionPxMode, nodeInfo.Symbol); m_context.Log(msg, MessageType.Error, true); continue; } int len = sec.Bars.Count; // Валидирую наличие правильной котировки if (sec.FinInfo != null) { Debug.WriteLine("AskPx: " + sec.FinInfo.Ask); Debug.WriteLine("BidPx: " + sec.FinInfo.Bid); } recalc = true; if ((m_optionPxMode == OptionPxMode.Ask) && (m_qty > 0) || (m_optionPxMode == OptionPxMode.Bid) && (m_qty < 0)) { string signalName = "\r\nLeft-Click BUY \r\n" + eventArg.Point.Tooltip + "\r\n"; posMan.BuyAtPrice(m_context, sec, Math.Abs(m_qty), nodeInfo.OptPx, signalName, null); } else if ((m_optionPxMode == OptionPxMode.Bid) && (m_qty > 0) || (m_optionPxMode == OptionPxMode.Ask) && (m_qty < 0)) { string signalName = "\r\nLeft-Click SELL \r\n" + eventArg.Point.Tooltip + "\r\n"; posMan.SellAtPrice(m_context, sec, Math.Abs(m_qty), nodeInfo.OptPx, signalName, null); } else if (m_optionPxMode == OptionPxMode.Mid) { string msg = String.Format("[{0}] OptionPxMode.Mid is not implemented.", m_optionPxMode); m_context.Log(msg, MessageType.Alert, true); } else if (m_qty == 0) { string msg = String.Format("[{0}] Qty: {1}. Trading is blocked.", m_optionPxMode, m_qty); m_context.Log(msg, MessageType.Warning, true); } } catch (Exception ex) { string msg = String.Format("[{0}] {1} in RouteOnClickEvents. Message: {2}\r\n{3}", m_optionPxMode, ex.GetType().FullName, ex.Message, ex); m_context.Log(msg, MessageType.Alert, true); } } if (recalc) { m_context.Recalc(); } }