public void GetHistory(GetHistoryCtx aCtx, HistoryAnswerHandler aCallback) { try { double lastPrice = GetLastPrice(aCtx.Request.Selection.Symbol); List <Bar> bars; switch (aCtx.Request.Selection.Periodicity) { case Periodicity.Tick: bars = GenerateTickHistory(aCtx.Request.Selection.Interval, aCtx.MaxBars, lastPrice); break; case Periodicity.Range: bars = GenerateRangeHistory(aCtx.Request.Selection.Interval, aCtx.MaxBars, lastPrice); break; default: bars = GenerateHistory(aCtx.Request.Selection, aCtx.MaxBars, lastPrice); break; } bars.Reverse(); aCallback(aCtx, bars); } catch (Exception e) { WriteToLog("GetHistory", e); } }
public void RunBacktest(BacktestGetRequest aRequest) { var errorString = TradeScript.ValidateBuySell(aRequest.BuyScript, aRequest.SellScript); if (aRequest.BuyScript == string.Empty || aRequest.SellScript == string.Empty) { errorString = "Buy and sell script can not be empty"; } if (errorString != string.Empty) { var response = new BacktestGetResponse { Id = aRequest.Id, Error = errorString, User = aRequest.User }; PushResponses(aRequest.User.ID, new ResponseMessage[] { response }); return; } var selection = new HistoryParameters(aRequest.Id, aRequest.Symbol, aRequest.Periodicity, aRequest.Interval, aRequest.BarsCount); IDataFeed aDataFeed = GetDataFeedByName(aRequest.Symbol.DataFeed); if (aDataFeed != null) { GetHistoryCtx aCtx = GetHistoryCtx(selection, aDataFeed.TimeZoneInfo); aCtx.Request = new HistoryRequest(selection); aCtx.DataFeed = aDataFeed; ThreadPool.QueueUserWorkItem(o => { aDataFeed.GetHistory(aCtx, (ctx, bars) => { string backtestOutput = TradeScript.Backtest(aRequest.BuyScript, aRequest.SellScript, bars); var response = new BacktestGetResponse { Id = aRequest.Id, User = aRequest.User, Symbol = aRequest.Symbol, Information = TradeScript.ExtractBacktestInformation(backtestOutput), Trades = TradeScript.ExtractBacktestTrades(backtestOutput) }; PushResponses(aRequest.User.ID, new ResponseMessage[] { response }); }); }); } }
private void GetHistoryRequest(HistoryRequest aRequest) { Validate(aRequest); IDataFeed aDataFeed = GetDataFeedByName(aRequest.Selection.Symbol.DataFeed); if (aDataFeed != null) { GetHistoryCtx aCtx = GetHistoryCtx(aRequest.Selection, aDataFeed.TimeZoneInfo); aCtx.Request = aRequest; aCtx.DataFeed = aDataFeed; ThreadPool.QueueUserWorkItem(o => { aDataFeed.GetHistory(aCtx, Get1MinHistoryCallback); }); } }
private void GetDayHistoryCallback(GetHistoryCtx aCtx, List <Bar> aBars) { try { List <Bar> aList2 = new List <Bar>(); aBars.ForEach(o => { WriteToLog_Info(String.Format("DateTime: {0}", o.Date.ToString("yy-MM-dd")), null); o.Date = TimeZoneInfo.ConvertTimeToUtc(o.Date, aCtx.DataFeed.TimeZoneInfo); }); aBars = aBars.OrderBy(o => o.Date).ToList(); // response contains bars for a previous day if (aBars.Count > 0) { DateTime aUTCFrom; DateTime aUTCTo; aUTCFrom = aBars[0].Date; aUTCTo = TimeZoneInfo.ConvertTimeToUtc(aCtx.ToF); } aCtx.Bars.AddRange(aList2.OrderByDescending(o => o.Date)); // send response HistoryResponse aResponse = new HistoryResponse(); aResponse.Bars = CalculateBars(aCtx, aCtx.Bars); aResponse.ID = aCtx.Request.Selection.Id; aResponse.User = aCtx.Request.User; PushResponse(aResponse); } catch (Exception e) { WriteToLog("GetDayHistoryCallback", e); try { aCtx.Request.User.SendError(new ApplicationException(String.Format("Historical request (ID='{0}')", aCtx.Request.Selection.Id))); } catch { } } }
private void Get1MinHistoryCallback(GetHistoryCtx aCtx, List <Bar> aBars) { HistoryResponse aResponse = new HistoryResponse(); var tZone = aCtx.DataFeed.TimeZoneInfo; /*foreach (var b in aBars) * { * b.Date = TimeZoneInfo.ConvertTimeToUtc(b.Date, tZone); * }*/ aResponse.Bars = aBars; aResponse.ID = aCtx.Request.Selection.Id; aResponse.User = aCtx.Request.User; if (aCtx.Request.Selection.GenerateChartImage) { aResponse.ChartImageData = OHLCPainter.GenerateChartAsJsonString(aBars); } PushResponse(aResponse); }
private bool NeedConvertBars(GetHistoryCtx aCtx) { return((aCtx.Request.Selection.Periodicity == Periodicity.Hour && aCtx.Request.Selection.Interval >= 18) || (aCtx.Request.Selection.Periodicity == Periodicity.Month && aCtx.Request.Selection.Interval > 1) || aCtx.Request.Selection.Periodicity == Periodicity.Year); }
public void GetHistory(GetHistoryCtx aCtx, HistoryAnswerHandler aCallback) { List <Bar> aBars = new List <Bar>(); //doesn't support if (aCtx.Request.Selection.Periodicity == Periodicity.Tick || aCtx.Request.Selection.Periodicity == Periodicity.Range) { aCallback(aCtx, aBars); return; } try { string aData; if (aCtx.FromF.Year < 1900) { aCtx.FromF = new DateTime(1900, 1, 1); } string aURL = BuildUrl2(aCtx.Request.Selection, aCtx.FromF, aCtx.ToF, aCtx.MaxBars); string dateFormat; int dateColumn; if (aCtx.Request.Selection.Periodicity >= Periodicity.Day) { dateFormat = "yyyy-MM-dd"; dateColumn = 1; } else { dateFormat = "yyyy-MM-dd HH:mm"; dateColumn = 0; } string[] aRows; aData = OpenURL(aURL); aRows = aData.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); foreach (string item in aRows) { Bar aBar = new Bar(); string[] aCells = item.Split(','); if (aCells.Length == 7) { aBar.Date = DateTime.ParseExact(aCells[dateColumn], dateFormat, null); aBar.Date = TimeZoneInfo.ConvertTimeToUtc(aBar.Date, TimeZoneInfo);// aBar.Open = Double.Parse(aCells[2], m_Culture.NumberFormat); if (Math.Abs(aBar.Open) < Double.Epsilon) { continue; } aBar.High = Double.Parse(aCells[3], m_Culture.NumberFormat); aBar.Low = Double.Parse(aCells[4], m_Culture.NumberFormat); aBar.Close = Double.Parse(aCells[5], m_Culture.NumberFormat); aBar.Volume = Int64.Parse(aCells[6], m_Culture.NumberFormat); } else { throw new ApplicationException("History response is not valid: " + aData); } aBars.Add(aBar); } aBars.Reverse(); } catch (Exception e) { WriteToLog("GetHistory", e); } if (NeedConvertBars(aCtx)) { aBars = CombineBars(aBars, aCtx.Request.Selection.Periodicity, aCtx.Request.Selection.Interval); } aCallback(aCtx, aBars); }
private GetHistoryCtx GetHistoryCtx(HistoryParameters aParameters, TimeZoneInfo datafeedTimeZone) { int nBars = aParameters.BarsCount; DateTime aFromF; DateTime aToF; int maxBars = nBars; if (aParameters.Interval != 1) { nBars = aParameters.Interval * nBars; } if ((aParameters.From == DateTime.MinValue || aParameters.From == DateTime.MaxValue) && (aParameters.To == DateTime.MinValue || aParameters.To == DateTime.MaxValue)) { TimeZoneInfo aTZI = datafeedTimeZone; DateTime aUTCNow = DateTime.UtcNow; aToF = TimeZoneInfo.ConvertTimeFromUtc(aUTCNow, aTZI); switch (aParameters.Periodicity) { case Periodicity.Second: aFromF = aToF.Date.AddMinutes(-nBars); //not supported break; case Periodicity.Minute: //need check if (aParameters.Symbol.Type == Instrument.Forex) { double nDays = 3.0 * (1 + nBars / (24.0 * 60.0) * (7.0 / 5.0)); aFromF = aToF.Date.AddDays(-(int)nDays); } else { aFromF = aToF.Date.AddMinutes(-6 * nBars - 5000); } break; case Periodicity.Hour: //need check if (aParameters.Symbol.Type == Instrument.Forex) { double nDays = 3.0 * (1 + nBars / (24.0) * (7.0 / 5.0)); aFromF = aToF.Date.AddDays(-(int)nDays); } else { aFromF = aToF.Date.AddMinutes(-6 * nBars * 24 - 5000); } break; case Periodicity.Day: aFromF = aToF.Date.AddDays(-(int)nBars * 7 / 5); break; case Periodicity.Week: aFromF = aToF.Date.AddDays(-(int)7 * nBars * 7 / 5); break; case Periodicity.Month: aFromF = aToF.Date.AddMonths(-nBars); maxBars = nBars; break; case Periodicity.Year: aToF = new DateTime(aToF.Year, 1, 1); aFromF = aToF.Date.AddYears(-nBars); nBars *= 12; maxBars = nBars; break; default: System.Diagnostics.Debug.Assert(false); aFromF = aToF.Date.AddMinutes(-nBars); break; } aParameters.To = TimeZoneInfo.ConvertTimeToUtc(aToF, aTZI); aParameters.From = TimeZoneInfo.ConvertTimeToUtc(aFromF, aTZI); } else if (aParameters.From == DateTime.MinValue || aParameters.From == DateTime.MaxValue || aParameters.To == DateTime.MinValue || aParameters.To == DateTime.MaxValue) { throw new ApplicationException("Hitory period is specified incorrectly"); } else { TimeZoneInfo aTZI = datafeedTimeZone; DateTime aUTCNow = DateTime.UtcNow; aToF = TimeZoneInfo.ConvertTimeFromUtc(aParameters.To, aTZI); aFromF = TimeZoneInfo.ConvertTimeFromUtc(aParameters.From, aTZI).Date; aParameters.From = TimeZoneInfo.ConvertTimeToUtc(aFromF, aTZI); } GetHistoryCtx aCtx = new GetHistoryCtx(); aCtx.MaxBars = maxBars; //aCtx.Request = aRequest; aCtx.Bars = new List <Bar>(); aCtx.FromF = aFromF; aCtx.ToF = aToF; //aCtx.DataFeed = aDataFeed; aCtx.Interval = aParameters.Interval; return(aCtx); }
private List <Bar> CalculateBars(GetHistoryCtx aCtx, List <Bar> aPrimitives) { List <Bar> aList = new List <Bar>(); if (aCtx.Bars.Count == 0) { return(aList); } if (aCtx.Request.Selection.Periodicity == Periodicity.Minute) { int aInterval = aCtx.Interval; if (aInterval > 1) { int i = 0; aCtx.Bars.Reverse(); while (i < aCtx.Bars.Count) { DateTime aStart = aCtx.Bars[i].Date; int aRest = 0; Bar aBar = new Bar(); List <Bar> aList2; int i2; aRest = aStart.TimeOfDay.Minutes % aInterval; if (aRest != 0) { aStart = aStart.AddMinutes(-aRest); } i2 = aCtx.Bars.FindIndex(i, o => o.Date >= aStart.AddMinutes(aInterval)); if (i2 >= i) { if (i2 > i) { aList2 = aCtx.Bars.GetRange(i, Math.Min(i2 - i, aInterval)); } else { aList2 = new List <Bar>(); aList2.Add(aCtx.Bars[i]); } aBar.Date = aStart; aBar.Open = aList2[0].Open; aBar.Close = aList2[aList2.Count - 1].Close; aBar.High = aList2.Max(o => o.High); aBar.Low = aList2.Min(o => o.Low); aBar.Volume = aList2.Sum(o => o.Volume); aStart = aStart.AddMinutes(aInterval); aList.Add(aBar); i += aList2.Count(); } else { break; } } aList.Reverse(); } else { aList.AddRange(aPrimitives); } } else if (aCtx.Request.Selection.Periodicity == Periodicity.Day) { return(aCtx.Bars); } else { return(aCtx.Bars); } return(aList); }
private void SubscribeAlert(AlertSubscribeRequest aRequest) { var errorString = TradeScript.Validate(aRequest.Script); if (aRequest.Script == string.Empty) { errorString = "Script can not be empty"; } if (errorString != string.Empty) { var response = new AlertSubscribeResponse { Id = aRequest.Id, Error = errorString, AlertName = aRequest.AlertName, Alert = new Alert { Name = aRequest.Name, Symbol = aRequest.Symbol }, User = aRequest.User }; PushResponses(aRequest.User.ID, new ResponseMessage[] { response }); return; } var selection = new HistoryParameters(aRequest.Id, aRequest.Symbol, aRequest.Periodicity, aRequest.Interval, aRequest.BarsCount); IDataFeed aDataFeed = GetDataFeedByName(aRequest.Symbol.DataFeed); if (aDataFeed != null) { GetHistoryCtx aCtx = GetHistoryCtx(selection, aDataFeed.TimeZoneInfo); aCtx.Request = new HistoryRequest(selection); aCtx.DataFeed = aDataFeed; ThreadPool.QueueUserWorkItem(o => { aDataFeed.GetHistory(aCtx, (ctx, bars) => { Level1Subscribers subscribers = null; var symbolItem = new SymbolItem() { DataFeed = aRequest.Symbol.DataFeed, Exchange = aRequest.Symbol.Exchange, Symbol = aRequest.Symbol.Symbol, Type = aRequest.Symbol.Type }; lock (m_Level1SubscribersBySymbols) { if (!m_Level1SubscribersBySymbols.TryGetValue(aRequest.Symbol, out subscribers)) { subscribers = new Level1Subscribers(); subscribers.Subscribers = new List <string>(); subscribers.AlertSubscribers = new List <AlertSubscription>(); m_Level1SubscribersBySymbols.Add(aRequest.Symbol, subscribers); } } AlertSubscription alert = new AlertSubscription() { Id = aRequest.Id, AlertName = aRequest.AlertName, Symbol = symbolItem, Name = aRequest.Name, Periodicity = aRequest.Periodicity, Interval = aRequest.Interval, Script = aRequest.Script, UserSessionId = aRequest.User.ID, Login = aRequest.User.Login, CalculationType = aRequest.CalculationType }; alert.InitAlert(bars); lock (subscribers.AlertSubscribers) { subscribers.AlertSubscribers.Add(alert); } aDataFeed.Subscribe(aRequest.Symbol); }); }); } }