/// <summary>
        /// распаковать если необходимо
        /// </summary>
        public List <QuoteData> GetQuotes()
        {
            if (!packed)
            {
                return(unpacked);
            }

            var result         = new List <QuoteData>(count);
            var unpackedStream = method == PackedMethod.FastGZip
                ? UnpackBytesGZip(quoteStream)
                : CompressionHelper.DecompressBytes(quoteStream);
            const int quoteSz = SizeofTime + SizeofPrice + SizeofPrice;
            var       size    = count * quoteSz;

            for (var offset = 0; offset < size; offset += quoteSz)
            {
                var q = new QuoteData
                {
                    time = new DateTime(BitConverter.ToInt64(unpackedStream, offset)),
                    ask  = BitConverter.ToSingle(unpackedStream, offset + SizeofTime),
                    bid  = BitConverter.ToSingle(unpackedStream, offset + SizeofTime + SizeofPrice)
                };
                result.Add(q);
            }

            return(result);
        }
Beispiel #2
0
        public bool IsValid(string symbol, QuoteData quote)
        {
            var logMsgCode = symbol.GetHashCode();

            var price = (quote.ask + quote.bid) * 0.5f;
            if (price < MinValue)
            {
                logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Debug, logMsgCode, 1000 * 60 * 120,
                    "Котировка {0} ({1}) меньше допустимого значения {2}",
                    symbol, price, MinValue);
                return false;
            }

            float val;
            if (!quoteByTicker.TryGetValue(symbol, out val))
                return true;

            var delta = Math.Abs(price - val) / val;
            if (delta > MaxDeltaRel)
            {
                logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Debug, logMsgCode, 1000 * 60 * 120,
                    "Котировка {0} ({1}): последнее сохраненное значение {2}",
                    symbol, price, val);
                return false;
            }

            return true;
        }
        /// <summary>
        /// Читает котировки из файла. Строки вида:   EURUSD	1.371825	09.12.2013 16:09:35
        /// </summary>
        private static Dictionary<string, QuoteData> ReadFromFile()
        {
            var result = new Dictionary<string, QuoteData>();

            var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DAL\\last_quotes.txt");

            string[] lines;
            try
            {
                lines = File.ReadAllLines(filePath);
            }
            catch (Exception ex)
            {
                Logger.Error("ReadFromFile", ex);
                return result;
            }

            if (lines.Length == 0) return result;

            foreach (var quoteItemes in lines.Select(line => line.Split('\t')))
            {
                float bid;
                if (Single.TryParse(quoteItemes[1].Trim(), out bid)) continue;

                var ticker = quoteItemes[0].Trim();
                if (!result.Keys.Contains(ticker)) continue;
                var quote = new QuoteData(bid, DalSpot.Instance.GetAskPriceWithDefaultSpread(ticker, bid), DateTime.Now);
                result.Add(ticker, quote);
            }

            return result;
        }
Beispiel #4
0
 public bool PricesAreSame(QuoteData q)
 {
     if (q == null)
     {
         return(false);
     }
     return(bid == q.bid && ask == q.ask);
 }
Beispiel #5
0
 public static QuoteData ParseQuoteStringNewFormat(string line,
     DateTime date)
 {
     // 0000 1.3570 1.3572
     var parts = line.Split(' ');
     if (parts.Length != 3) return null;
     var quote = new QuoteData();
     var timeNum = int.Parse(parts[0]);
     int hour = timeNum / 100;
     int minute = timeNum - 100 * hour;
     quote.time = date.AddMinutes(minute + hour * 60);
     quote.bid = parts[1].ToFloatUniform();
     quote.ask = parts[2].ToFloatUniform();
     return quote;
 }
Beispiel #6
0
        public static QuoteData ParseQuoteStringNewFormat(string line,
                                                          DateTime date)
        {
            // 0000 1.3570 1.3572
            var parts = line.Split(' ');

            if (parts.Length != 3)
            {
                return(null);
            }
            var quote   = new QuoteData();
            var timeNum = int.Parse(parts[0]);
            int hour    = timeNum / 100;
            int minute  = timeNum - 100 * hour;

            quote.time = date.AddMinutes(minute + hour * 60);
            quote.bid  = parts[1].ToFloatUniform();
            quote.ask  = parts[2].ToFloatUniform();
            return(quote);
        }
        /// <summary>
        /// Расчитать объем сделки в валюте депозита
        /// </summary>
        public void CalculateDealVolumeInDepoCurrency(MarketOrder deal, QuoteData dealQuote, string depoCurrency, QuoteArchive arc, DateTime date)
        {
            var volumeInCounter = deal.Volume * dealQuote.GetPrice(QuoteType.NonSpecified);

            // перевести из контрвалюты в валюту депо
            bool inverse, pairsAreEqual;
            var smb = DalSpot.Instance.FindSymbol(deal.Symbol, false, depoCurrency, out inverse, out pairsAreEqual);
            if (pairsAreEqual)
            {
                deal.VolumeInDepoCurrency = volumeInCounter;
                return;
            }

            if (string.IsNullOrEmpty(smb)) return;
            var quoteCtDepo = arc.GetQuoteOnDateSeq(smb, date);
            if (quoteCtDepo == null) return;
            var priceCtDepo = quoteCtDepo.GetPrice(QuoteType.NonSpecified);
            if (priceCtDepo == 0) return;

            deal.VolumeInDepoCurrency = inverse ? volumeInCounter / priceCtDepo : volumeInCounter * priceCtDepo;
        }
        public CandleDataBidAsk[] MakeCandles(QuoteData[] quotes, ref string[] names)
        {
            var candles = new CandleDataBidAsk[quotes.Length];

            List<int> indexesLacked = null;

            for (var i = 0; i < quotes.Length; i++)
            {
                CandlePackerBidAsk packer;
                if (!packers.TryGetValue(names[i], out packer))
                {
                    logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error, LogMsgPackerForTickerMissed,
                        1000 * 60 * 5, "CandlePackerPool - не найден пакер для тикера {0}, всего {1} пакеров",
                        names[i], packers.Count);

                    if (indexesLacked == null)
                        indexesLacked = new List<int> {i};
                    else
                        indexesLacked.Add(i);

                    continue;
                }
                var candle = packer.UpdateCandle(quotes[i]);
                candles[i] = candle;
            }

            if (indexesLacked != null)
            {
                if (indexesLacked.Count == quotes.Length)
                {
                    names = new string[0];
                    return new CandleDataBidAsk[0];
                }
                names = names.Where((n, i) => !indexesLacked.Contains(i)).ToArray();
                candles = candles.Where((n, i) => !indexesLacked.Contains(i)).ToArray();
            }

            return candles;
        }
        /// <summary>
        /// распаковать если необходимо
        /// </summary>
        public List<QuoteData> GetQuotes()
        {
            if (!packed) return unpacked;

            var result = new List<QuoteData>(count);
            var unpackedStream = method == PackedMethod.FastGZip
                ? UnpackBytesGZip(quoteStream)
                : CompressionHelper.DecompressBytes(quoteStream);
            const int quoteSz = SizeofTime + SizeofPrice + SizeofPrice;
            var size = count * quoteSz;

            for (var offset = 0; offset < size; offset += quoteSz)
            {
                var q = new QuoteData
                            {
                                time = new DateTime(BitConverter.ToInt64(unpackedStream, offset)),
                                ask = BitConverter.ToSingle(unpackedStream, offset + SizeofTime),
                                bid = BitConverter.ToSingle(unpackedStream, offset + SizeofTime + SizeofPrice)
                            };
                result.Add(q);
            }

            return result;
        }
        private int CheckProtectByDivers(QuoteData curQuote, bool isHistoryStartOff, StringBuilder diverKinds)
        {
            if (diversToProtect.Count == 0) return 0;
            var diverSign = 0;
            foreach (var diverSet in diversToProtect)
            {
                var candle = packerDiverProtect[diverSet].UpdateCandle(curQuote.bid, curQuote.time);
                if (candle == null) continue;
                var candleQueue = candles4Protect[diverSet];
                candleQueue.Add(candle);

                // сформировалась новая свеча - проверить дивергенции с индексами);
                foreach (var diver in diverSet.IndexList)
                {
                    diver.CalculateValue(tickerNames, candleQueue, lastBidLists, curTime, randomGener);
                    if (isHistoryStartOff) continue;
                    string divergenceText;
                    var indiDiverSign = diver.GetDivergenceSign(candleQueue, out divergenceText);
                    //if (!string.IsNullOrEmpty(divergenceText))
                    //    Logger.InfoFormat("CheckProtectTrigger[{0}]: {1}",
                    //    BarSettingsStorage.Instance.GetBarSettingsFriendlyName(diverSet.Timeframe),
                    //    divergenceText);
                    diverSign += indiDiverSign;
                    if (indiDiverSign != 0 && ShowProtectEventMarker)
                    {
                        diverKinds.Append(BarSettingsStorage.Instance.GetBarSettingsFriendlyName(diverSet.timeframe));
                        diverKinds.Append(indiDiverSign > 0 ? ":Б " : ":М ");
                    }
                }
            }
            return -diverSign;
        }
        /// <param name="newQuotes">обновленные котировки</param>
        /// <returns>нужна перерисовка</returns>
        public bool ProcessQuotes(QuoteData[] newQuotes)
        {
            if (newQuotes == null) return false;
            // выдерживание минимального интервала между обновлениями
            var deltaMills = (DateTime.Now - timeOfLastUpdate).TotalMilliseconds;
            if (deltaMills < MinIntervalBetweenUpdates)
                return false;

            timeOfLastUpdate = DateTime.Now;
            // доукомплектовать свечки
            if (newQuotes.Length == 0) return false;
            if (candlePacker == null) return false;
            var candles = chart.StockSeries.Data.Candles;
            // обновленная свечка и список добавленных свечек
            CandleData updatedCandle = null;
            var newCandles = new List<CandleData>();

            foreach (var q in newQuotes)
            {
                if (q.bid == 0 || q.ask == 0)
                {
                    Logger.ErrorFormat("Nil quote: {0} at {1}",
                                       Symbol, q.time, q.bid == 0 && q.ask == 0 ? " both" : "");
                    continue;
                }
                var candle = candlePacker.UpdateCandle(q.bid, q.time);
                if (candle == null) continue;

                // либо завершена старая свечка, либо слеплена новая
                if (candles.Count > 0)
                    if (candles[candles.Count - 1].timeOpen == candle.timeOpen)
                    {
                        candles[candles.Count - 1] = new CandleData(candle); // заменить обновленную
                        // запомнить обновленную свечку
                        updatedCandle = candles[candles.Count - 1];
                        continue;
                    }
                candles.Add(new CandleData(candle));
                // запомнить добавленную свечку
                newCandles.Add(candles[candles.Count - 1]);
            }
            // если сформировалась, но не закончена новая свеча...
            if (candlePacker.CurrentCandle != null)
            {
                var candleUpdated = false;
                if (candles.Count > 0)
                    if (candles[candles.Count - 1].timeOpen == candlePacker.CurrentCandle.timeOpen)
                    {
                        candles[candles.Count - 1] = new CandleData(candlePacker.CurrentCandle); // заменить обновленную
                        // запомнить обновленную свечку
                        updatedCandle = candles[candles.Count - 1];
                        candleUpdated = true;
                    }
                if (!candleUpdated)
                {
                    candles.Add(new CandleData(candlePacker.CurrentCandle));
                    // запомнить добавленную свечку
                    newCandles.Add(candles[candles.Count - 1]);
                }
            }

            // обновить границу интервала
            if (newQuotes.Length > 0)
                chart.EndTime = newQuotes[newQuotes.Length - 1].time;

            // обработать котировки в индикаторах
            ProcessQuotesByIndicators(updatedCandle, newCandles);

            if (chart.StockSeries.ShowLastQuote)
            {
                float? price = newCandles.Count > 0
                     ? newCandles[newCandles.Count - 1].close
                     : updatedCandle != null
                     ? (float?)updatedCandle.close : null;
                if (price.HasValue)
                    chart.Panes.StockPane.YAxis.CurrentPrice = price;
            }

            if (chart.StockSeries.AutoScroll)
                chart.ScrollToEnd();
            return true;
        }
        private void MakeOrder(string expertComment, string comment, int dealSign, 
            QuoteData curQuote, List<string> hints)
        {
            var tradeVolume = GetEnterVolume();
            if (tradeVolume == 0)
            {
                hints.Add(comment + ", объем входа 0");
                return;
            }

            var order = new MarketOrder
                {
                    ExpertComment = expertComment, // описание проекции
                    Comment = comment,
                    Symbol = ticker,
                    Volume = tradeVolume,
                    Side = dealSign,
                    //StopLoss =
                };

            // запрос входа на сервере
            var status = NewOrder(order, OrderType.Market,
                                  (decimal) (dealSign > 0 ? curQuote.ask : curQuote.bid), 0);
            if (status != RequestStatus.OK)
                hints.Add(comment + ", вход неуспешен: " + status);
        }
Beispiel #13
0
 private void UpdateQuote(News[] news, QuoteData[] quotes)
 {
     if (!startupFinished) return;
     if (!updateCompleted.WaitOne(UpdateQuoteTimeout)) return;
     updateCompleted.Reset();
     try
     {
         // график обрабатывает новые котировки и перерисовывается
         var flagRedrawQuotes = false;
         var flagRedrawNews = false;
         if (quotes != null)
             flagRedrawQuotes = chart.ProcessQuotes(quotes);
         if (news != null)
             flagRedrawNews = chart.ProcessNews(news);
         if (flagRedrawNews || flagRedrawQuotes) // перерисовать
         {
             chart.RedrawChartSafe();
         }
     }
     finally
     {
         updateCompleted.Set();
     }
 }
Beispiel #14
0
        /// <summary>
        /// асинхронно обновить график
        /// </summary>        
        public void UpdateBaseNewsAsynch(News[] news, QuoteData[] quotes)
        {
            if (!updateCompleted.WaitOne(WaitFormUpdateInterval)) return;

            var del = new UpdateQuoteDel(UpdateQuote);
            try
            {
                BeginInvoke(del, (object)news, (object)quotes);
            }
            catch (InvalidOperationException) { }
        }
        private AccountStatistics BuildEquityCurve(
            List<MarketOrder> orders, 
            List<MarketOrder> openOrders,
            List<BalanceChange> balanceChanges)
        {
            var stat = new AccountStatistics
                           {
                               Statistics = new PerformerStat
                                   {
                                       DealsCount = orders.Count + openOrders.Count,
                                   },
                               DealsStillOpened = openOrders.Count,
                               listEquity = new List<EquityOnTime>()
                           };
            if (worker.CancellationPending) return stat;
            SetProgressValueSafe(40, Localizer.GetString("MessageActualizingQuoteHistory") + "...");

            if (balanceChanges.Count == 0)
            {
                MessageBox.Show(Localizer.GetString("MessageNoTransfersData"));
                return stat;
            }
            var curxDepo = AccountStatus.Instance.AccountData.Currency;
            // запросить котировки, если стоит соотв. флаг
            var quotesDic = UpdateQuotesForStats(orders, openOrders, curxDepo);

            // построить кривую эквити
            // отсчет от первого движения на счете либо от стартовой даты
            balanceChanges = balanceChanges.OrderBy(bc => bc.ValueDate).ToList();
            var startDate = cbStartFrom.Checked ? dpStart.Value : balanceChanges[0].ValueDate;

            // начальный баланс
            var initialBalance = !cbStartFrom.Checked ? balanceChanges[0].SignedAmountDepo
                : balanceChanges.Where(bc => bc.ValueDate <= startDate).Sum(bc => bc.SignedAmountDepo);

            // движения от начального баланса с заданным интервалом дискретизации
            var dueBalances = balanceChanges.Where(bc => bc.ValueDate > startDate).ToList();
            var dueDeals = orders.Union(openOrders).OrderBy(o => o.TimeEnter).ToList();

            var endDate = DateTime.Now;
            var balance = initialBalance;

            var cursor = new BacktestTickerCursor();
            var path = ExecutablePath.ExecPath + TerminalEnvironment.QuoteCacheFolder;
            if (!cursor.SetupCursor(path, quotesDic.Keys.ToList(), quotesDic.Min(t => t.Value)))
            {
                MessageBox.Show(Localizer.GetString("MessageErrorGettingQuotesFromFiles"));
                return stat;
            }
            var currentQuotes = new Dictionary<string, QuoteData>();
            var timeframeMinutes = Timeframe;
            SetProgressValueSafe(60, Localizer.GetString("MessageCalculationInProcess") + "...");
            try
            {
                for (var time = startDate; time < endDate; time = time.AddMinutes(timeframeMinutes))
                {
                    if (worker.CancellationPending) return stat;
                    // получить баланс на дату
                    for (var i = 0; i < dueBalances.Count; i++)
                    {
                        if (dueBalances[i].ValueDate > time) break;
                        balance += dueBalances[i].SignedAmountDepo;
                        dueBalances.RemoveAt(i);
                        i--;
                    }
                    var equity = balance;

                    // получить текущие котировки
                    var candles = cursor.MoveToTime(time);
                    foreach (var candle in candles)
                    {
                        var quote = new QuoteData(candle.Value.open,
                                                  DalSpot.Instance.GetAskPriceWithDefaultSpread(candle.Key,
                                                                                                candle.Value.open),
                                                  candle.Value.timeOpen);

                        if (currentQuotes.ContainsKey(candle.Key))
                            currentQuotes[candle.Key] = quote;
                        else
                            currentQuotes.Add(candle.Key, quote);
                    }

                    // уточнить результат по открытым позициям
                    for (var i = 0; i < dueDeals.Count; i++)
                    {
                        if (worker.CancellationPending) return stat;
                        if (dueDeals[i].TimeExit.HasValue)
                            if (dueDeals[i].TimeExit.Value <= time)
                            {
                                dueDeals.RemoveAt(i);
                                i--;
                                continue;
                            }
                        var deal = dueDeals[i];
                        if (deal.TimeEnter <= time)
                        {
                            // посчитать текущий результат сделки
                            // в контрвалюте
                            if (!currentQuotes.ContainsKey(deal.Symbol)) continue;
                            var dealTickerQuote = currentQuotes[deal.Symbol];
                            var dealTickerPrice = deal.Side > 0 ? dealTickerQuote.bid : dealTickerQuote.ask;
                            var dealResult = deal.Volume * deal.Side * (dealTickerPrice - deal.PriceEnter);

                            // перевод прибыли в валюту депо
                            bool inverse, areSame;
                            var dealTransferSymbol = DalSpot.Instance.FindSymbol(deal.Symbol,
                                                                                 false, curxDepo, out inverse,
                                                                                 out areSame);
                            float? baseDepoRate = null;
                            if (areSame) baseDepoRate = 1f;
                            else
                            {
                                if (!string.IsNullOrEmpty(dealTransferSymbol))
                                    if (currentQuotes.ContainsKey(dealTransferSymbol))
                                    {
                                        var quote = currentQuotes[dealTransferSymbol];
                                        if (quote.time >= time)
                                            baseDepoRate = !inverse
                                                               ? (deal.Side > 0 ? quote.bid : quote.ask)
                                                               : (deal.Side > 0 ? 1 / quote.ask : 1 / quote.bid);
                                    }
                            }
                            if (!baseDepoRate.HasValue) continue;
                            dealResult *= baseDepoRate.Value;
                            equity += (decimal)dealResult;
                        }
                    } // for (deal ...
                    // сохранить отметку - время/доходность
                    stat.listEquity.Add(new EquityOnTime((float)equity, time));
                } // for (time ... += Timeframe
            }
            finally
            {
                cursor.Close();
            }
            // если история начинается с пустого депо - изъять эти строки из истории
            var firstNotEmpty = stat.listEquity.FindIndex(e => e.equity > 0);
            if (firstNotEmpty == stat.listEquity.Count - 1) stat.listEquity.Clear();
            else
                if (firstNotEmpty > 0) stat.listEquity.RemoveRange(0, firstNotEmpty);

            SetProgressValueSafe(70,
                Localizer.GetString("MessageBuildingEquityChart") + "...");
            stat.Calculate(balanceChanges, openOrders, startDate);
            return stat;
        }
Beispiel #16
0
 public Mt4Quote(string symbol, QuoteData quote)
 {
     Symbol = symbol;
     Bid = quote.bid;
     Ask = quote.ask;
 }
Beispiel #17
0
        /// <summary>
        /// считаемтся суммарный ордер
        /// текущая котировка берется из curQuote, если таковая null - из
        /// avgPrice
        /// </summary>
        public MarketOrder CalculateSummaryOrder(List<MarketOrder> orders, 
            QuoteData curQuote, float? avgPrice)
        {
            if (orders.Count == 0) return null;
            if (orders.Count == 1) return orders[0].MakeCopy();
            var symbol = orders[0].Symbol;

            float sumBuys = 0, sumSells = 0;
            var sumVolume = 0;
            var totalProfit = 0f;
            foreach (var order in orders)
            {
                sumVolume += order.Side * order.Volume;
                if (order.Side > 0)
                    sumBuys += order.Volume * order.PriceEnter;
                else
                    sumSells += order.Volume * order.PriceEnter;
                totalProfit += order.ResultDepo;
            }
            var miniPipCost = GetAbsValue(symbol, 1/10f);

            if (sumVolume != 0)
            {
                var averagePrice = (sumBuys - sumSells) / sumVolume;
                var avgOrder = new MarketOrder
                {
                    Symbol = orders[0].Symbol,
                    PriceEnter = averagePrice,
                    ResultDepo = totalProfit,
                    Side = Math.Sign(sumVolume),
                    Volume = Math.Abs(sumVolume),
                    StopLoss = GetDefaultSample(orders.Select(o => o.StopLoss), true, miniPipCost),
                    TakeProfit = GetDefaultSample(orders.Select(o => o.TakeProfit), true, miniPipCost),
                };

                var price = avgPrice;
                if (curQuote != null)
                    price = avgOrder.Side > 0 ? curQuote.bid : curQuote.ask;

                avgOrder.ResultPoints = price.HasValue
                    ? (int)Math.Round(GetPointsValue(symbol, avgOrder.Side * (price.Value -
                    avgOrder.PriceEnter))) : 0;
                return avgOrder;
            }

            return null;
        }
Beispiel #18
0
 private static void OnQuotesReceived(string[] names, QuoteData[] quotes)
 {
     ModuleStatusController.Instance.lastQuoteTime.Value = DateTime.Now;
 }
Beispiel #19
0
        /// <summary>
        /// Вызывается с приходом новой котировки
        /// </summary>
        public override List<string> OnQuotesReceived(string[] names, QuoteData[] quotes, bool isHistoryStartOff)
        {
            if (isHistoryStartOff) return null;

            List<MarketOrder> orders;

            robotContext.GetMarketOrders(robotContext.accountInfo.ID, out orders);

            if (orders == null || orders.Count == 0)
                StateRobot = StateInfo.NoTrade;
            if (quotes[0] == null) return null;

            for (var i = 0; i < names.Count(); i++)
            {
                // пробегаемся по тикерам и ищем те на которые подписан робот
                foreach (var ticker in Graphics)
                {
                    if (ticker.a == names[i])
                    {
                        //BarSettings set = ticker.b;
                        //var dt = set.GetDistanceTime(15, -1, quotes[i].Time);

                        // валютная пара совпадает
                        if (StateRobot == StateInfo.NoTrade)
                        {
                            // надо открыть позицию допустим buy
                            var sl = quotes[i].ask - DalSpot.Instance.GetAbsValue(ticker.a, (float) (StopLoss ?? 0));
                            var tp = quotes[i].ask + DalSpot.Instance.GetAbsValue(ticker.a, (float) (TakeProfit ?? 0));
                            if (NewOrder(Magic, ticker.a, 10000, 1, OrderType.Market, 0, 0, (decimal?)sl,
                                     (decimal?)tp, null, null, string.Empty, "simple_robot") == RequestStatus.OK)
                            {
                                StateRobot = StateInfo.OpenBuy;
                            }
                        }
                    }
                }
            }
            return null;
        }
Beispiel #20
0
        public void CheckOrderTrailing(MarketOrder pos, QuoteData price)
        {
            const int minPipsToMoveStop = 1;

            if (!pos.TrailLevel1.HasValue) return;
            var resultAbs = pos.Side > 0 ? price.bid - pos.PriceEnter : pos.PriceEnter - price.ask;
            var resultPoints = DalSpot.Instance.GetPointsValue(pos.Symbol, resultAbs);
            for (var i = pos.trailingLevels.Length - 1; i >= 0; i--)
            {
                if ((pos.trailingLevels[i] == null) || (pos.trailingTargets[i] == null)) continue;
                if (resultPoints >= pos.trailingLevels[i].Value)
                {
                    // перетащить стоп
                    var targetStop = pos.PriceEnter + pos.Side *
                                     DalSpot.Instance.GetAbsValue(pos.Symbol, pos.trailingTargets[i].Value);
                    if ((pos.StopLoss == null || (targetStop > pos.StopLoss && pos.Side > 0) ||
                         (targetStop < pos.StopLoss && pos.Side < 0)))
                    {
                        // проверить расстояние между целевым стопом и текущим стопом
                        var deltaSlPips = Math.Abs(DalSpot.Instance.GetPointsValue(pos.Symbol,
                                                                                   targetStop - (pos.StopLoss ?? 0)));
                        if (deltaSlPips >= minPipsToMoveStop)
                        {
                            // вот тут уж точно перетащить стоп
                            Logger.InfoFormat("Установка SL для позиции #{0} с {1:f5} на {2:f5}",
                                              pos.ID, pos.StopLoss ?? 0, targetStop);
                            MoveStop(pos, targetStop);
                            break;
                        }
                    }
                }
            }
        }
        private void CheckScriptTriggerQuote(string[] quoteNames, QuoteData[] quoteArray)
        {
            // сформировать список скриптов (по котировке и по формуле) для срабатывания
            var scriptsToFire = new List<TerminalScript>();
            var scripts = ScriptManager.Instance.GetScripts().ToList();
            foreach (var script in scripts.Where(s => s.Trigger != null &&
                                                      (s.Trigger is ScriptTriggerNewQuote ||
                                                       s.Trigger is ScriptTriggerPriceFormula)
                                                       /*&& s.ScriptTarget != TerminalScript.TerminalScriptTarget.График*/))
            {
                if (script.Trigger is ScriptTriggerNewQuote)
                {
                    var trigger = (ScriptTriggerNewQuote) script.Trigger;
                    if (trigger.quotesToCheck.Count == 0 ||
                        trigger.quotesToCheck.Any(q => quoteNames.Any(n => n.Equals(q, StringComparison.OrdinalIgnoreCase))))
                    {
                        scriptsToFire.Add(script);
                    }
                    continue;
                }
                if (script.Trigger is ScriptTriggerPriceFormula)
                {
                    var trigger = (ScriptTriggerPriceFormula) script.Trigger;
                    trigger.CheckCondition();
                    if (trigger.IsTriggered)
                        scriptsToFire.Add(script);
                }
            }

            // запустить скрипты на выполнение
            if (scriptsToFire.Count > 0)
                ThreadPool.QueueUserWorkItem(ExecuteScriptsRoutine, scriptsToFire);
        }
Beispiel #22
0
        /// <summary>
        /// получена котировка - одна или несколько
        /// обновить графики
        /// </summary>        
        private void OnQuotesReceived(string[] names, QuoteData[] quotes)
        {
            // определить, сколько времени прошло с момента получения последней котировки
            // предложить заполнить дырки
            var lastQuoteTime = lastQuoteReceived.GetLastHitIfHitted() ?? timeStarted;
            var deltaMinutes = (DateTime.Now - lastQuoteTime).TotalMinutes;
            if (deltaMinutes > MinutesOfGapInQuoteStream)
                ReportOnGapFound(lastQuoteTime);
            // обновить время последней котировки
            lastQuoteReceived.Touch();
            robotFarm.OnQuotesReceived(names, quotes);
            try
            {
                for (var i = 0; i < names.Length; i++)
                {
                    var name = names[i];
                    var charts = Charts;
                    for (var j = 0; j < charts.Count; j++)
                    {
                        var child = charts[j];
                        if (child.chart.Symbol != name) continue;
                        // обновить асинхронно
                        child.UpdateQuoteAsynch(new[] {quotes[i]});
                    }
                }
            }
            // ReSharper disable EmptyGeneralCatchClause
            catch
            // ReSharper restore EmptyGeneralCatchClause
            {// окно может быть еще не сформировано, когда в него попадет котировка
            }

            // обработать котировки в скриптах
            CheckScriptTriggerQuote(names, quotes);
        }
        /// <summary>
        /// проверить условия защиты либо по диверам, либо - по Фибоначчи
        /// прошерстить все таймфреймы, на каждом ТФ - все диверы
        /// проверить, выполняется ли условие на защиту покупок или продаж
        /// </summary>
        private void CheckProtectTrigger(
            List<MarketOrder> orders,
            QuoteData curQuote,
            List<RobotHint> hints,
            bool isHistoryStartOff,
            CandleData newCandle)
        {
            if (diversToProtect.Count == 0 && fibonacciProtect.Count == 0) return;

            var protectConditions = new StringBuilder();
            int diverSign = CheckProtectByDivers(curQuote, isHistoryStartOff, protectConditions);
            if (diverSign == 0)
                diverSign = CheckProtectByFibos(protectConditions, orders, newCandle);
            if (diverSign == 0) return;
            // защищаем сделки с указанным знаком
            var protectSide = (DealType) diverSign;
            // создать новый список защиты
            // старый либо актуализируется, либо игнорируется
            orders = orders.Where(o => o.Side == (int)protectSide).ToList();
            if (orders.Count == 0) return;

            var newProtectList = new ProtectList
            {
                orderIds = orders.Select(o => o.ID).ToList(),
                side = protectSide
            };
            if (protectList != null)
                if (newProtectList.AreEqual(protectList)) return;
            protectList = newProtectList;

            // добавить маркер на график
            if (ShowProtectEventMarker)
            {
                var eventTitle = protectSide == DealType.Buy
                    ? string.Format("Защита {0} покупок", orders.Count)
                    : string.Format("Защита {0} продаж", orders.Count);
                var eventText = "Условия: " + protectConditions;
                hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(), eventText, eventTitle, "p", curQuote.bid)
                {
                    Time = curQuote.time,
                    ColorFill = Color.Yellow,
                    ColorLine = Color.Black,
                    RobotHintType = RobotHint.HintType.Коментарий
                        //diverSign > 0
                        //    ? RobotHint.HintType.Покупка
                        //    : RobotHint.HintType.Продажа
                });
            }
            //Logger.InfoFormat("CheckProtectTrigger: защита сделок [{0}] типа {1}",
            //                  string.Join(", ", protectList.orderIds), protectList.side);
        }
        /// <summary>
        /// проверить и осуществить трейлинг
        /// </summary>
        private void CheckUnconditionalProtect(List<MarketOrder> orders, QuoteData curQuote,
            List<RobotHint> hints)
        {
            foreach (var order in orders)
            {
                var result = order.Side > 0
                                 ? curQuote.bid - order.PriceEnter
                                 : order.PriceEnter - curQuote.ask;
                var resultPoints = DalSpot.Instance.GetPointsValue(order.Symbol, result);
                if (resultPoints < unconditionalProtectPips) continue;
                var stop = order.PriceEnter + order.Side *
                           DalSpot.Instance.GetAbsValue(order.Symbol, (float)protectTarget);
                var deltaPips = DalSpot.Instance.GetPointsValue(order.Symbol, Math.Abs(stop - (order.StopLoss ?? 0)));
                if (deltaPips <= protectSensitivity) continue;

                // передвинуть стоп
                order.StopLoss = stop;
                robotContext.SendEditMarketRequest(protectedContext.MakeProtectedContext(), order);
                if (ShowProtectMarker)
                {
                    var title = "Безусловная защита сделки " + order.ID;
                    hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(), title, title, "p", curQuote.bid)
                    {
                        RobotHintType = RobotHint.HintType.Коментарий,
                        Time = curQuote.time,
                        ColorFill = Color.White,
                        ColorLine = Color.DarkBlue,
                        ColorText = Color.Black
                    });
                }
            }
        }
        public override List<string> OnQuotesReceived(string[] names, QuoteData[] quotes, bool isHistoryStartOff)
        {
            if (formulaResolver == null || packer == null) return null;
            curTime = quotes[0].time;

            // обновить табличку цен
            for (var i = 0; i < names.Length; i++)
            {
                if (lastBids.ContainsKey(names[i]))
                    lastBids[names[i]] = quotes[i].bid;
                else
                    lastBids.Add(names[i], quotes[i].bid);
            }

            QuoteData curQuote = null;
            for (var i = 0; i < names.Length; i++)
                if (names[i] == ticker)
                {
                    curQuote = quotes[i];
                    break;
                }

            if (curQuote == null) return null; // нет торгуемой котировки

            // обновить свечки
            var candle = packer.UpdateCandle(curQuote.bid, curQuote.time);
            Dictionary<string, double> varValues = null;
            if (candle != null)
            {
                candles.Add(candle);
                countCandles++;
                // обновить очереди (для индекса, переменные вида usdjpy#15)
                if (lastBidLists.Count > 0)
                {
                    foreach (var listTicker in lastBidLists)
                    {
                        float price;
                        if (!lastBids.TryGetValue(listTicker.Key, out price)) price = 0;
                        listTicker.Value.Add(price);
                    }
                }
                // посчитать индекс
                double index;
                varValues = GetVariableValues();
                if (formulaResolver.Calculate(varValues, out index))
                    lastIndexValue = double.IsNaN(index) ? 0 : (float)index;
                lastIndicies.Add(lastIndexValue ?? 0);
            }

            // если это период "разгона" конвейера
            if (isHistoryStartOff) return null;

            RobotHint hint = null;

            // получить знак дивергенции
            if (candle != null)
            {
                string commentOnDivergence = string.Empty;
                var divergenceSign = GetDivergenceSign(out commentOnDivergence);
                List<MarketOrder> orders;
                robotContext.GetMarketOrders(robotContext.accountInfo.ID, out orders);
                if (divergenceSign != 0)
                {
                    var hintText = new StringBuilder();
                    hintText.AppendLine(commentOnDivergence);
                    hintText.AppendLine("Переменные:");
                    // ReSharper disable PossibleNullReferenceException)
                    foreach (var pair in varValues)
                        // ReSharper restore PossibleNullReferenceException
                    {
                        hintText.AppendLine(string.Format("{1}{0}{2:f4}", (char) 9, pair.Key, pair.Value));
                    }

                    hint = new RobotHint(Graphics[0].a, Graphics[0].b.ToString(),
                        hintText.ToString(), divergenceSign > 0 ? "BUY" : "SELL", "e", curQuote.bid)
                               {
                                   Time = candle.timeOpen,
                                   //curTime
                                   ColorFill = divergenceSign > 0 ? Color.Green : Color.Red,
                                   ColorLine = Color.Black,
                                   RobotHintType = divergenceSign > 0
                                                       ? RobotHint.HintType.Покупка
                                                       : RobotHint.HintType.Продажа
                               };

                    // если получен сигнал на покупку - купить, закрыв продажи
                    // наоборот, если получен сигнал на продажу - продать, закрыв покупки
                    var ordersToClose = orders.FindAll(o => o.Side != divergenceSign);
                    foreach (var order in ordersToClose)
                    {
                        robotContext.SendCloseRequest(CurrentProtectedContext.Instance.MakeProtectedContext(),
                            robotContext.accountInfo.ID, order.ID, PositionExitReason.ClosedByRobot);
                    }

                    // открыть позу в направлении знака дивера
                    decimal? stop = StopLossPoints == 0
                                        ? (decimal?) null
                                        : (decimal)curQuote.bid -
                                          divergenceSign*DalSpot.Instance.GetAbsValue(ticker, (decimal)StopLossPoints);
                    decimal? take = TakeProfitPoints == 0
                                        ? (decimal?) null
                                        : (decimal)curQuote.bid +
                                          divergenceSign*DalSpot.Instance.GetAbsValue(ticker, (decimal)TakeProfitPoints);

                    robotContext.SendNewOrderRequest(CurrentProtectedContext.Instance.MakeProtectedContext(),
                                                     RequestUniqueId.Next(), robotContext.accountInfo.ID, Magic, ticker, Volume,
                                                     divergenceSign, OrderType.Market, 0, 0,
                                                     stop, take, null, null, string.Empty, "OscillatorBasedRobot");
                }
            }

            return hint != null ? new List<string> {hint.ToString()} : null;
        }
Beispiel #26
0
 public QuoteData(QuoteData q)
 {
     bid  = q.bid;
     ask  = q.ask;
     time = q.time;
 }
Beispiel #27
0
        public float CalculateProfit(QuoteData q)
        {
            var priceExit = Side > 0 ? q.bid : q.ask;

            return(CalculateProfit(priceExit));
        }
Beispiel #28
0
        private void OnQuotesReceived(string[] names, QuoteData[] quotes)
        {
            var nowTime = DateTime.Now.AddDays(offsetHours);

            // лок на запись в словарь свечей
            if (!lockCandles.TryEnterWriteLock(LockTimeout))
            {
                Logger.Error("OnQuotesReceived - таймаут записи");
                return;
            }

            try
            {
                if (!lockCandlesM1.TryEnterWriteLock(LockTimeout))
                {
                    Logger.Error("OnQuotesReceived - таймаут записи (m1)");
                    return;
                }

                try
                {
                    // обновить свечи
                    foreach (var packerDic in packers)
                    {
                        var timeframeCode = packerDic.Key;
                        var isM1 = timeframeCode == barSettingsCodeM1;

                        for (var i = 0; i < names.Length; i++)
                        {
                            var name = names[i];
                            CandlePacker packer;
                            packerDic.Value.TryGetValue(name, out packer);
                            if (packer == null) continue;
                            var newCandle = packer.UpdateCandle(quotes[i].bid, nowTime);
                            if (newCandle != null)
                            {
                                candles[timeframeCode][name].Add(newCandle);
                                if (isM1) candlesM1[name].Add(newCandle);
                            }
                        }
                    }
                }
                finally
                {
                    lockCandlesM1.ExitWriteLock();
                }
            }
            finally
            {
                lockCandles.ExitWriteLock();
            }

            // если пришло время выгрузить m1 в файл... выгрузить
            var timeSaved = lastTimeCandlesSaved.GetLastHitIfHitted();
            if (timeSaved.HasValue)
            {
                if ((DateTime.Now - timeSaved.Value).TotalSeconds > flushCandlesIntervalSec)
                {
                    FlushCandlesInFiles(); // таки выгрузить
                    lastTimeCandlesSaved.Touch();
                }
            }
            else lastTimeCandlesSaved.Touch();
        }
 public CandleDataBidAsk UpdateCandle(QuoteData q)
 {
     var candleBid = packerBid.UpdateCandle(q.bid, q.time) ?? packerBid.CurrentCandle;
     var candleAsk = packerAsk.UpdateCandle(q.ask, q.time) ?? packerAsk.CurrentCandle;
     return new CandleDataBidAsk(candleBid, candleAsk)
         {
             timeClose = q.time
         };
 }
Beispiel #30
0
 /// <summary>
 /// асинхронно обновить график
 /// </summary>        
 public void UpdateQuoteAsynch(QuoteData[] quotes)
 {
     UpdateBaseNewsAsynch(null, quotes);
 }
        private void TryEnterTheMarket(int divergenceSign, QuoteData curQuote,
            List<RobotHint> hints, string divergenceHint)
        {
            // проверить фильтры
            foreach (var filter in filters)
            {
                if (filter.IsEnterProhibided((DealType)divergenceSign))
                    return; // запрет входа фильтром
            }
            // фильтр Фибоначчпхи
            if (FiboEnabled)
                if (!IsFiboFilterPassed(divergenceSign)) return;

            List<MarketOrder> orders;
            GetMarketOrders(out orders);
            var ordersCount = orders.Count;

            // закрыть противоположные ордера
            var ordersToClose = orders.FindAll(o => o.Side != divergenceSign);

            foreach (var order in ordersToClose)
            {
                var requestRst = robotContext.SendCloseRequest(protectedContext.MakeProtectedContext(),
                    robotContext.AccountInfo.ID, order.ID, PositionExitReason.ClosedByRobot);
                // добавить объект - коментарий на график
                if (ShowExitMarker)
                {
                    var orderResult = order.Side == 1
                                          ? curQuote.bid - order.PriceEnter
                                          : order.PriceEnter - curQuote.ask;
                    orderResult = DalSpot.Instance.GetPointsValue(order.Symbol, orderResult);
                    var dealInfo = new StringBuilder();
                    dealInfo.AppendLine(string.Format(
                        "{0} №{1}. {2}, р-т {3}",
                        requestRst == RequestStatus.OK
                            ? "Закрытие"
                            : "[" + requestRst + "]",
                        order.ID,
                        order.Side == 1 ? "BUY" : "SELL",
                        (int) orderResult));
                    dealInfo.Append(string.Format("Открыта {0:dd.MM.yyyy HH:mm} по {1:f4}",
                                                  order.TimeEnter, order.PriceEnter));

                    hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(),
                        divergenceHint, dealInfo.ToString(), "q", curQuote.bid)
                                  {
                                      Time = curQuote.time,
                                      ColorFill = order.Side == 1 ? Color.Green : Color.Red,
                                      ColorLine = Color.Black,
                                      RobotHintType = RobotHint.HintType.Коментарий
                                  });
                }
                ordersCount--;
            }

            // открыть позу в направлении знака дивера
            if (!OpenDeal(divergenceSign, orders)) return;

            if (ShowEnterMarker)
                hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(),
                    divergenceHint, divergenceSign > 0 ? "BUY" : "SELL", "e", curQuote.bid)
                              {
                                  Time = curQuote.time,
                                  ColorFill = divergenceSign > 0 ? Color.Green : Color.Red,
                                  ColorLine = Color.Black,
                                  RobotHintType =
                                      divergenceSign > 0
                                          ? RobotHint.HintType.Покупка
                                          : RobotHint.HintType.Продажа
                              });
        }
        private int GetSignalSide(List<string> hints, QuoteData curQuote, 
            out string comment, out string expertComment)
        {
            comment = string.Empty;
            expertComment = string.Empty;

            // есть ли "пробитая" проекция?
            string projString;
            var projSign = GetLastProjectionSide(out projString);
            if (projSign == 0) return 0;

            // есть ли дивер?
            var diverSpan = GetDivergence();
            var lastSign = diverSpan == null ? 0 : diverSpan.sign;

            if (lastSign == 0) return 0;

            // знаки не совпали - входа нет
            if (lastSign != projSign)
            {
                if (ExtendedMarks)
                    hints.Add(new RobotHint(ticker, BarSettingsStorage.Instance.GetBarSettingsFriendlyName(timeframe),
                         string.Format("Знаки расширения {0} и дивергенции [{1}:{2}] не совпали",
                            projString, diverSpan.sign > 0 ? "бычья" : "медвежья",
                            candles[diverSpan.end].timeClose.ToStringUniform()), "Нет входа", "", curQuote.bid
                        )
                    {
                        Time = curQuote.time,
                        ColorFill = Color.LightGreen,
                        ColorLine = Color.Black,
                        RobotHintType = lastSign > 0 ? RobotHint.HintType.Покупка
                            : RobotHint.HintType.Продажа
                    }.ToString());
                return 0;
            }

            if (diverSpan != null)
            {
                expertComment = projString;
                comment = string.Format("Ф: {0}, дивер: [{1}:{2}]",
                                        projString,
                                        diverSpan.sign > 0 ? "бычья" : "медвежья",
                                        candles[diverSpan.end].timeOpen.ToStringUniform());
            }

            // вернуть знак предполагаемого входа в рынок
            return lastSign;
        }
        /// <summary>
        /// собственно защита
        /// </summary>        
        private void CheckProtect(List<MarketOrder> orders, QuoteData curQuote,
            List<RobotHint> hints)
        {
            if (protectList == null) return;
            if (protectList.orderIds.Count == 0)
            {
                protectList = null;
                return;
            }
            var ordersToProtect = (from order in orders let orderId = order.ID where
                                       protectList.orderIds.Contains(orderId) select order).ToList();
            if (ordersToProtect.Count == 0) return;

            var pointCost = DalSpot.Instance.GetAbsValue(ordersToProtect[0].Symbol, 1f);

            // индивидуальная "защита"
            if (ProtectPosType == ProtectType.Индивидуально)
            {
                foreach (var order in ordersToProtect)
                {
                    var targetStop = order.PriceEnter + order.Side*ProtectTarget*pointCost;
                    // проверка - не пытаться переставить стоп на 0.4 пп например
                    var delta = Math.Abs(targetStop - (order.StopLoss ?? 0));
                    delta = delta/pointCost;
                    if (delta < ProtectSensitivity) continue;
                    // проверка контрольной отметки
                    var orderProtectLevel = order.PriceEnter + order.Side*ProtectLevel*pointCost;
                    var shouldProtect = order.Side == 1
                                            ? curQuote.bid > orderProtectLevel
                                            : curQuote.bid < orderProtectLevel;
                    if (!shouldProtect) continue;
                    order.StopLoss = targetStop;
                    robotContext.SendEditMarketRequest(protectedContext.MakeProtectedContext(), order);
                    if (ShowProtectMarker)
                    {
                        var title = "Защита сделки " + order.ID;
                        hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(), title, title, "p", curQuote.bid)
                                      {
                                          RobotHintType = RobotHint.HintType.Коментарий,
                                          Time = curQuote.time,
                                          ColorFill = Color.White,
                                          ColorLine = Color.DarkBlue,
                                          ColorText = Color.Black
                                      });
                    }
                    protectList.orderIds.Remove(order.ID);
                }
                if (protectList.orderIds.Count == 0) protectList = null;
                return;
            }

            // защита по "медианнной цене" или по "худшей цене"
            // найти ту самую медианную цену
            float medPrice = 0;
            if (ProtectPosType == ProtectType.ПоСреднейЦене)
            { // средняя цена...
                var sumPrice = ordersToProtect.Sum(o => o.PriceEnter * o.Volume);
                var sumVolume = ordersToProtect.Sum(o => o.Volume);
                medPrice = sumPrice/sumVolume;
            }
            if (ProtectPosType == ProtectType.ПоХудшейЦене)
            {
                var date = ordersToProtect[0].TimeEnter;
                medPrice = ordersToProtect[0].PriceEnter;
                for (var i = 1; i < ordersToProtect.Count; i++)
                {
                    if (ordersToProtect[i].TimeEnter >= date) continue;
                    date = ordersToProtect[i].TimeEnter;
                    medPrice = ordersToProtect[i].PriceEnter;
                }
            }

            var stopPrice = medPrice + ordersToProtect[0].Side * ProtectTarget * pointCost;
            // проверить все ордера
            var dealProtected = false;
            foreach (var order in ordersToProtect)
            {
                var delta = Math.Abs(stopPrice - (order.StopLoss ?? 0));
                delta = delta / pointCost;
                if (delta < ProtectSensitivity) continue;
                // цена прошла рубеж?
                var shouldProtect = order.Side == 1
                                            ? curQuote.bid > medPrice
                                            : curQuote.bid < medPrice;
                if (!shouldProtect) continue;
                dealProtected = true;
                order.StopLoss = stopPrice;
                protectList.orderIds.Remove(order.ID);
            }
            if (ShowProtectMarker && dealProtected)
            {
                var text = new StringBuilder();
                text.AppendLine("Защита сделок " + string.Join(", ", ordersToProtect.Select(o => o.ID)));
                text.AppendFormat("Средневзвеш. цена: {0:f4}", medPrice);
                hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(), "Защита сделок", text.ToString(), "p", curQuote.bid)
                {
                    RobotHintType = RobotHint.HintType.Коментарий,
                    Time = curQuote.time,
                    ColorFill = Color.White,
                    ColorLine = Color.DarkBlue,
                    ColorText = Color.Black
                });
            }

            if (protectList.orderIds.Count == 0) protectList = null;
            return;
        }
Beispiel #34
0
        protected int CalculateVolumeInBaseCurrency(decimal volumeDepo, string tradeTicker,
            VolumeRoundType roundType, QuoteData quoteByTicker = null)
        {
            var volumeBase = volumeDepo;

            var depoCurx = robotContext.AccountInfo.Currency;
            var quotes = QuoteStorage.Instance.ReceiveAllData();
            bool inverse, pairsEqual;
            var tickerTrans = DalSpot.Instance.FindSymbol(tradeTicker, true, depoCurx,
                out inverse, out pairsEqual);

            if (!pairsEqual)
            {
                QuoteData quote;
                if (tickerTrans == tradeTicker && quoteByTicker != null)
                    quote = quoteByTicker;
                else
                    quotes.TryGetValue(tickerTrans, out quote);
                if (quote == null)
                {
                    var msgError = string.Format(
                        "Невозможно рассчитать объем - отсутствует котировка \"{0}\"", tickerTrans);
                    Logger.Info(msgError);
                    return 0;
                }
                var priceTrans = inverse ? 1 / quote.bid : quote.ask;
                volumeBase /= (decimal)priceTrans;
            }

            return MarketOrder.RoundDealVolume((int)volumeBase, roundType, RoundMinVolume, RoundVolumeStep);
        }
Beispiel #35
0
 public void OnQuotesReceived(string[] names, QuoteData[] quotes)
 {
     if (State != FarmState.Started) return;
     // if (RobotFarmOffTime.IsTimeOff()) return;
     var candles = packerPool.MakeCandles(quotes, ref names);
     foreach (var account in Accounts)
     {
         try
         {
             account.OnQuotesReceived(names, candles, false);
         }
         catch (Exception ex)
         {
             Logger.Error("Ошибка обработки котировок по счету " + account.AccountId + ": " + ex.Message);
         }
     }
 }