public ActualizedInstrument[] GetActualizedInstruments() { return (_reader.GetAvaliableInstrumentNames().Select(o => new ActualizedInstrument() { Name = o, DateFrom = _reader.GetMinDateTimeStamp(o).AddMonths(3), DateTo = _reader.GetMaxDateTimeStamp(o) }).ToArray()); }
private void CalculateNextOrder(CalculationOrder order, bool saveResults = false) { var datefrom = order.DateFrom.AddMonths(-3); if (_reader.GetMinDateTimeStamp(order.InstrumentName) > datefrom) { Logger.Log(" ERROR: incorrect data in order DATE FROM."); return; } var candles = _reader.GetCandles(order.InstrumentName, order.Period, datefrom, order.DateTo); if (order.IgnoreNightCandles) { candles = candles.Where(o => o.DateTimeStamp.Hour <= nightHoursStart && o.DateTimeStamp.Hour >= nightHoursEnd).ToArray(); } var tickers = candles.Select(o => o.Ticker).Distinct() .OrderBy(o => candles.Where(c => c.Ticker == o).Max(d => d.DateTimeStamp)).ToArray(); var strategy = (IStrategy)Activator.CreateInstance(_strategyType); for (var i = 0; i < order.Parameters.Count(); i++) { strategy.Parameters[i].Value = order.Parameters[i]; } var outDatas = new List <object[]>(); var balances = new List <float>(); var balancesPerDeal = new List <float>(); var lastResult = StrategyResult.Exit; var balance = 0f; var priceDiff = 0f; var lotSize = 0; var lastPrice = 0f; var stopPrice = 0f; var gapValue = float.MinValue; float maxBalancePerDeal = float.MinValue; foreach (var ticker in tickers) { var tc = candles.Where(o => o.Ticker == ticker).OrderBy(o => o.DateTimeStamp).ToList(); lastResult = StrategyResult.Exit; var itemDateFrom = _reader.GetItemDateFrom(ticker); if (order.DateFrom > itemDateFrom) { itemDateFrom = order.DateFrom; } var startIndex = tc.FindIndex(o => o.DateTimeStamp >= itemDateFrom); if (startIndex == -1) { continue; } if (strategy.AnalysisDataLength > startIndex) { Logger.Log(string.Format("ERROR: order id {0}, preload data count < data count needed for analysis!", order.Id)); return; } strategy.Initialize(); var currentSL = 0f; strategy.StopLossValue = order.StopLoss; EventHandler <float> stopLossChanged = (sender, newVal) => { if (currentSL != 0) { if (lastResult == StrategyResult.Long) { if (newVal > lastPrice - order.StopLoss) { currentSL = newVal; } } if (lastResult == StrategyResult.Short) { if (newVal < lastPrice + order.StopLoss) { currentSL = newVal; } } } }; strategy.OnStopLossChanged += stopLossChanged; for (var i = startIndex; i < tc.Count; i++) { var data = tc.GetRange(i - strategy.AnalysisDataLength + 1, strategy.AnalysisDataLength).ToArray(); object[] outData; var result = strategy.Analyze(data, out outData); if ((i == tc.Count - 1) || ((tc[i].DateTimeStamp.Hour == nightHoursStart) && (order.IgnoreNightCandles))) { result = StrategyResult.Exit; } if (lastResult != result) { var closePrice = tc[i].Close; if (lastResult == StrategyResult.Long) { closePrice = closePrice - (IsInDay(tc[i].DateTimeStamp) ? order.DaySpread : order.NightSpread); } if (lastResult == StrategyResult.Short) { closePrice = closePrice + (IsInDay(tc[i].DateTimeStamp) ? order.DaySpread : order.NightSpread); } balance = balance + priceDiff + lotSize * closePrice; if (result == StrategyResult.Long) { lotSize = 1; priceDiff = -(tc[i].Close + (IsInDay(tc[i].DateTimeStamp) ? order.DaySpread : order.NightSpread)) * lotSize; if (order.StopLoss == 0) { currentSL = 0; } else { currentSL = tc[i].Close - order.StopLoss; } } if (result == StrategyResult.Short) { lotSize = -1; priceDiff = (tc[i].Close - (IsInDay(tc[i].DateTimeStamp) ? order.DaySpread : order.NightSpread)) * (-lotSize); if (order.StopLoss == 0) { currentSL = 0; } else { currentSL = tc[i].Close + order.StopLoss; } } if (result == StrategyResult.Exit) { priceDiff = 0; lotSize = 0; currentSL = 0; } balances.Add(balance); lastPrice = tc[i].Close; stopPrice = 0; balancesPerDeal.Add(balance); } else { balances.Add(balance + priceDiff + lotSize * tc[i].Close); if (currentSL != 0) { if (result == StrategyResult.Long) { if (tc[i].Close <= currentSL) { balance = balance + priceDiff + lotSize * (tc[i].Close - (IsInDay(tc[i].DateTimeStamp) ? order.DaySpread : order.NightSpread)); currentSL = 0; priceDiff = 0; lotSize = 0; stopPrice = tc[i].Close; } } if (result == StrategyResult.Short) { if (tc[i].Close >= currentSL) { balance = balance + priceDiff + lotSize * (tc[i].Close + (IsInDay(tc[i].DateTimeStamp) ? order.DaySpread : order.NightSpread)); currentSL = 0; priceDiff = 0; lotSize = 0; stopPrice = tc[i].Close; } } } } lastResult = result; var outList = new List <object>() { data.Last().DateTimeStamp, tc[i].Ticker, tc[i].Open, tc[i].High, tc[i].Low, tc[i].Close }; outList.AddRange(outData); outList.Add(lotSize); if (result == StrategyResult.Long) { outList.Add(currentSL); } if (result == StrategyResult.Short) { outList.Add(currentSL); } if (result == StrategyResult.Exit) { outList.Add(0); } if (stopPrice == 0) { outList.Add("No"); } else { outList.Add(string.Format("Yes ({0})", stopPrice)); } outList.Add(balance); if (saveResults) { outDatas.Add(outList.ToArray()); } if (balancesPerDeal.Any()) { if (maxBalancePerDeal < balancesPerDeal.Last()) { maxBalancePerDeal = balancesPerDeal.Last(); } if (gapValue < maxBalancePerDeal - balancesPerDeal.Last()) { gapValue = maxBalancePerDeal - balancesPerDeal.Last(); } } } strategy.OnStopLossChanged -= stopLossChanged; } var outDataDescription = new List <string>(); if (saveResults) { outDataDescription.AddRange(new string[6] { "Date Time", "Ticker", "Open", "High", "Low", "Close" }); outDataDescription.AddRange(strategy.OutDataDescription); outDataDescription.Add("LOT Size"); outDataDescription.Add("STOP price"); outDataDescription.Add("STOPPED"); outDataDescription.Add("Balance per deal"); } if (!saveResults) { balances.Clear(); } order.Result = new CalculationResult() { OutData = outDatas.Select(o => o.Select(obj => obj.ToString()).ToArray()).ToArray(), Balances = balances.ToArray(), OutDataDescription = outDataDescription.ToArray() }; order.TotalBalance = balance; order.Gap = gapValue; order.Status = CalculationOrderStatus.Finished; if (!saveResults) { _finishedOrders.Add(order); } }