public override string ActivateScript(string ticker) { if (!AccountStatus.Instance.isAuthorized) { MessageBox.Show("Не авторизован"); return("Не авторизован"); } var account = AccountStatus.Instance.AccountData; if (account == null) { MessageBox.Show("Не авторизован"); return("Не авторизован"); } var equity = account.Equity; if (equity <= 0) { MessageBox.Show("На счете отсутствуют денежные средства"); return("На счете отсутствуют денежные средства"); } var dealSide = side; decimal?sl = null, tp = null; float? trailLevel = null, trailTarget = null; // предполагаемая цена входа var quotes = QuoteStorage.Instance.ReceiveAllData(); QuoteData currentQuote; quotes.TryGetValue(ticker, out currentQuote); var reqPrice = currentQuote == null ? 0 : Side == DealType.Buy ? currentQuote.ask : currentQuote.bid; if (OrderType == ScriptOrderType.Отложенный && currentQuote == null) { return("Отложенный ордер не создан - нет котировки " + ticker); } // для отложенного ордера обязательно запросим цену decimal priceEnter = 0; float dealPrice = 0; if (RequestSide || OrderType == ScriptOrderType.Отложенный) { var dlg = new ScriptPartDepoFormDialog( (int)side, currentQuote == null ? (float?)null : currentQuote.bid, OrderType == ScriptOrderType.Отложенный) { TradeTicker = ticker }; if (dlg.ShowDialog() == DialogResult.Cancel) { return("Отменен"); } priceEnter = dlg.Price ?? 0; sl = dlg.SL; tp = dlg.TP; dealSide = (DealType)dlg.Side; if (dlg.Trailing != null && dlg.Trailing.Length == 2 && (dlg.Trailing[0] != 0 || dlg.Trailing[1] != 0)) { if (currentQuote == null) { var msg = string.Format("Нет котировки \"{0}\" для расчета пп трейлинга", ticker); MessageBox.Show(msg); return(msg); } var trailPrice = dlg.Trailing[0]; dealPrice = OrderType == ScriptOrderType.Отложенный ? (float)priceEnter : (dealSide == DealType.Buy ? currentQuote.ask : currentQuote.bid); var trailPips = DalSpot.Instance.GetPointsValue(ticker, ((int)dealSide) * (trailPrice - dealPrice)); // преобразовать цену в пп от входа trailLevel = trailPips; trailTarget = dlg.Trailing[1]; } } // объем в валюте депозита var volumeDepo = equity * leverage; var volumeBase = volumeDepo; // из объема депо пересчитать в объем базовой валюты var depoCurx = AccountStatus.Instance.AccountData.Currency; bool inverse, pairsEqual; var tickerTrans = DalSpot.Instance.FindSymbol(ticker, true, depoCurx, out inverse, out pairsEqual); if (!pairsEqual) { QuoteData quote; quotes.TryGetValue(tickerTrans, out quote); if (quote == null) { var msgError = string.Format( "Невозможно рассчитать объем - отсутствует котировка \"{0}\"", tickerTrans); MessageBox.Show(msgError); return(msgError); } var priceTrans = inverse ? 1 / quote.bid : quote.ask; volumeBase /= (decimal)priceTrans; } // округлить объем var lotSize = DalSpot.Instance.GetMinStepLot(ticker, account.Group); volumeBase = MarketOrder.RoundDealVolume((int)volumeBase, VolumeRound, lotSize.minVolume, lotSize.volumeStep); if (volumeBase == 0) { var msgError = $"Рассчетный объем входа ({volumeBase}) меньше допустимого ({lotSize.minVolume})"; MessageBox.Show(msgError); return(msgError); } // проверить количество входов (по тикеру либо вообще) var ordersCount = DealCounting == DealCountingType.ОбщийУчет ? MarketOrdersStorage.Instance.MarketOrders.Count : MarketOrdersStorage.Instance.MarketOrders.Count(o => o.Symbol == ticker); if (ordersCount >= dealsMax) { var msgError = DealCounting == DealCountingType.ОбщийУчет ? $"Уже открыто {ordersCount} сделок из {dealsMax} макс." : $"По \"{ticker}\" уже открыто {ordersCount} сделок из {dealsMax} макс."; MessageBox.Show(msgError); return(msgError); } // подтверждение var confirmPrice = dealPrice; if (confirmPrice == 0) { confirmPrice = (dealSide == DealType.Buy ? currentQuote.ask : currentQuote.bid); } if (confirmTrade) { if (MessageBox.Show(string.Format("Будет совершена {0} {1} {2} по {3}. Продолжить?", dealSide == DealType.Buy ? "покупка" : "продажа", volumeBase.ToStringUniformMoneyFormat(), depoCurx, confirmPrice.ToStringUniformPriceFormat()), "Подтверждение", MessageBoxButtons.YesNo) == DialogResult.No) { return("отменено пользователем"); } } // таки войти в рынок if (OrderType == ScriptOrderType.ыночный) { MainForm.Instance.SendNewOrderRequestSafe( RequestUniqueId.Next(), AccountStatus.Instance.accountID, new MarketOrder { Volume = (int)volumeBase, Side = (int)dealSide, Symbol = ticker, StopLoss = (float?)sl, TakeProfit = (float?)tp, TrailLevel1 = trailLevel, TrailTarget1 = trailTarget }, priceEnter, 0, Contract.Entity.OrderType.Market); } else { // создать отложенник var orderType = PendingOrderType.Limit; if (((int)dealSide == 1 && currentQuote.ask < (float)priceEnter) || ((int)dealSide == -1 && currentQuote.bid > (float)priceEnter)) { orderType = PendingOrderType.Stop; } var pendingOrder = new PendingOrder { AccountID = AccountStatus.Instance.accountID, Symbol = ticker, Volume = (int)volumeBase, Side = (int)dealSide, PriceSide = orderType, PriceFrom = (float)priceEnter, StopLoss = (float?)sl, TakeProfit = (float?)tp, TrailLevel1 = trailLevel, TrailTarget1 = trailTarget }; MainForm.Instance.SendNewPendingOrderRequestSafe(RequestUniqueId.Next(), pendingOrder); } return("Сделка с фиксированным плечом (" + dealSide + " " + ticker + ") совершена"); }
public override string ActivateScript(string ticker) { if (!AccountStatus.Instance.isAuthorized) { MessageBox.Show("Не авторизован"); return "Не авторизован"; } var account = AccountStatus.Instance.AccountData; if (account == null) { MessageBox.Show("Не авторизован"); return "Не авторизован"; } var equity = account.Equity; if (equity <= 0) { MessageBox.Show("На счете отсутствуют денежные средства"); return "На счете отсутствуют денежные средства"; } var dealSide = side; decimal? sl = null, tp = null; float? trailLevel = null, trailTarget = null; // предполагаемая цена входа var quotes = QuoteStorage.Instance.ReceiveAllData(); QuoteData currentQuote; quotes.TryGetValue(ticker, out currentQuote); var reqPrice = currentQuote == null ? 0 : Side == DealType.Buy ? currentQuote.ask : currentQuote.bid; if (OrderType == ScriptOrderType.Отложенный && currentQuote == null) { return "Отложенный ордер не создан - нет котировки " + ticker; } // для отложенного ордера обязательно запросим цену decimal priceEnter = 0; float dealPrice = 0; if (RequestSide || OrderType == ScriptOrderType.Отложенный) { var dlg = new ScriptPartDepoFormDialog( (int) side, currentQuote == null ? (float?)null : currentQuote.bid, OrderType == ScriptOrderType.Отложенный) { TradeTicker = ticker }; if (dlg.ShowDialog() == DialogResult.Cancel) return "Отменен"; priceEnter = dlg.Price ?? 0; sl = dlg.SL; tp = dlg.TP; dealSide = (DealType)dlg.Side; if (dlg.Trailing != null && dlg.Trailing.Length == 2 && (dlg.Trailing[0] != 0 || dlg.Trailing[1] != 0)) { if (currentQuote == null) { var msg = string.Format("Нет котировки \"{0}\" для расчета пп трейлинга", ticker); MessageBox.Show(msg); return msg; } var trailPrice = dlg.Trailing[0]; dealPrice = OrderType == ScriptOrderType.Отложенный ? (float)priceEnter : (dealSide == DealType.Buy ? currentQuote.ask : currentQuote.bid); var trailPips = DalSpot.Instance.GetPointsValue(ticker, ((int) dealSide)*(trailPrice - dealPrice)); // преобразовать цену в пп от входа trailLevel = trailPips; trailTarget = dlg.Trailing[1]; } } // объем в валюте депозита var volumeDepo = equity * leverage; var volumeBase = volumeDepo; // из объема депо пересчитать в объем базовой валюты var depoCurx = AccountStatus.Instance.AccountData.Currency; bool inverse, pairsEqual; var tickerTrans = DalSpot.Instance.FindSymbol(ticker, true, depoCurx, out inverse, out pairsEqual); if (!pairsEqual) { QuoteData quote; quotes.TryGetValue(tickerTrans, out quote); if (quote == null) { var msgError = string.Format( "Невозможно рассчитать объем - отсутствует котировка \"{0}\"", tickerTrans); MessageBox.Show(msgError); return msgError; } var priceTrans = inverse ? 1 / quote.bid : quote.ask; volumeBase /= (decimal)priceTrans; } // округлить объем var lotSize = DalSpot.Instance.GetMinStepLot(ticker, account.Group); volumeBase = MarketOrder.RoundDealVolume((int)volumeBase, VolumeRound, lotSize.a, lotSize.b); if (volumeBase == 0) { var msgError = string.Format( "Рассчетный объем входа ({0}) меньше допустимого ({1})", volumeBase, lotSize.a); MessageBox.Show(msgError); return msgError; } // проверить количество входов (по тикеру либо вообще) var ordersCount = DealCounting == DealCountingType.ОбщийУчет ? MarketOrdersStorage.Instance.MarketOrders.Count : MarketOrdersStorage.Instance.MarketOrders.Count(o => o.Symbol == ticker); if (ordersCount >= dealsMax) { var msgError = DealCounting == DealCountingType.ОбщийУчет ? string.Format( "Уже открыто {0} сделок из {1} макс.", ordersCount, dealsMax) : string.Format( "По \"{0}\" уже открыто {1} сделок из {2} макс.", ticker, ordersCount, dealsMax); MessageBox.Show(msgError); return msgError; } // подтверждение var confirmPrice = dealPrice; if (confirmPrice == 0) confirmPrice = (dealSide == DealType.Buy ? currentQuote.ask : currentQuote.bid); if (confirmTrade) if (MessageBox.Show(string.Format("Будет совершена {0} {1} {2} по {3}. Продолжить?", dealSide == DealType.Buy ? "покупка" : "продажа", volumeBase.ToStringUniformMoneyFormat(), depoCurx, confirmPrice.ToStringUniformPriceFormat()), "Подтверждение", MessageBoxButtons.YesNo) == DialogResult.No) return "отменено пользователем"; // таки войти в рынок if (OrderType == ScriptOrderType.Рыночный) MainForm.Instance.SendNewOrderRequestSafe( RequestUniqueId.Next(), AccountStatus.Instance.accountID, new MarketOrder { Volume = (int)volumeBase, Side = (int)dealSide, Symbol = ticker, StopLoss = (float?)sl, TakeProfit = (float?)tp, TrailLevel1 = trailLevel, TrailTarget1 = trailTarget }, priceEnter, 0, Contract.Entity.OrderType.Market); else { // создать отложенник var orderType = PendingOrderType.Limit; if (((int)dealSide == 1 && currentQuote.ask < (float)priceEnter) || ((int)dealSide == -1 && currentQuote.bid > (float)priceEnter)) orderType = PendingOrderType.Stop; var pendingOrder = new PendingOrder { AccountID = AccountStatus.Instance.accountID, Symbol = ticker, Volume = (int)volumeBase, Side = (int)dealSide, PriceSide = orderType, PriceFrom = (float)priceEnter, StopLoss = (float?)sl, TakeProfit = (float?)tp, TrailLevel1 = trailLevel, TrailTarget1 = trailTarget }; MainForm.Instance.SendNewPendingOrderRequestSafe(RequestUniqueId.Next(), pendingOrder); } return "Сделка с фиксированным плечом (" + dealSide + " " + ticker + ") совершена"; }