/// <summary> /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. /// </summary> /// <param name="data">TradeBars IDictionary object with your stock data</param> public void OnData(TradeBars data) { if (!_macd.IsReady) { return; } if (!data.ContainsKey(_ibm)) { return; } if (_lastAction.Date == Time.Date) { return; } _lastAction = Time; var holding = Portfolio[_spy]; if (holding.Quantity <= 0 && _macd > _macd.Signal && data[_ibm].Price > _ema) { SetHoldings(_ibm, 0.25m); } else if (holding.Quantity >= 0 && _macd < _macd.Signal && data[_ibm].Price < _ema) { SetHoldings(_ibm, -0.25m); } }
/// <summary> /// On receiving new tradebar data it will be passed into this function. The general pattern is: /// "public void OnData( CustomType name ) {...s" /// </summary> /// <param name="data">TradeBars data type synchronized and pushed into this function. The tradebars are grouped in a dictionary.</param> public void OnData(TradeBars data) { //int x = 0; //int y = 10; //int z = y / x; //if (!Portfolio.Invested) //{ // SetHoldings("SPY", 1); //} if (!Portfolio.HoldStock && data.ContainsKey("SPY")) { Order("SPY", (int)Math.Floor(Portfolio.Cash / data["SPY"].Close)); Debug("Debug Purchased MSFT: " + Portfolio.Cash); } if (Time.TimeOfDay.TotalSeconds % 10 == 0) { int i = Transactions.GetIncrementOrderId(); var order = new Order("BTC", 10, OrderType.Market, Time, data["BTC"].Price, "Tag: Test"); order.Status = OrderStatus.Filled; Transactions.Orders.AddOrUpdate<int, Order>(i, order); } }
/// <summary> /// On receiving new tradebar data it will be passed into this function. The general pattern is: /// "public void OnData( CustomType name ) {...s" /// </summary> /// <param name="data">TradeBars data type synchronized and pushed into this function. The tradebars are grouped in a dictionary.</param> public void OnData(TradeBars data) { //int x = 0; //int y = 10; //int z = y / x; //if (!Portfolio.Invested) //{ // SetHoldings("SPY", 1); //} if (!Portfolio.HoldStock && data.ContainsKey("SPY")) { Order("SPY", (int)Math.Floor(Portfolio.Cash / data["SPY"].Close)); Debug("Debug Purchased MSFT: " + Portfolio.Cash); } if (Time.TimeOfDay.TotalSeconds % 10 == 0) { int i = Transactions.GetIncrementOrderId(); var order = new Order("BTC", 10, OrderType.Market, Time, data["BTC"].Price, "Tag: Test"); order.Status = OrderStatus.Filled; Transactions.Orders.AddOrUpdate <int, Order>(i, order); } }
/// <summary> /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. /// </summary> /// <param name="data">TradeBars IDictionary object with your stock data</param> public void OnData(TradeBars data) { if (!macd.IsReady) { return; } if (!data.ContainsKey("IBM")) { return; } if (lastAction.Date == Time.Date) { return; } lastAction = Time; var holding = Portfolio["SPY"]; if (holding.Quantity <= 0 && macd > macd.Signal && data["IBM"].Price > ema) { SetHoldings("IBM", 0.25m); } else if (holding.Quantity >= 0 && macd < macd.Signal && data["IBM"].Price < ema) { SetHoldings("IBM", -0.25m); } }
/* * New data arrives here. * The "Slice" data represents a slice of time, it has all the data you need for a moment. */ public override void OnData(Slice data) { // slice has lots of useful information TradeBars bars = data.Bars; Splits splits = data.Splits; Dividends dividends = data.Dividends; //Get just this bar. TradeBar bar; if (bars.ContainsKey("SPY")) { bar = bars["SPY"]; } if (!Portfolio.HoldStock) { // place an order, positive is long, negative is short. // Order("SPY", quantity); // or request a fixed fraction of a specific asset. // +1 = 100% long. -2 = short all capital with 2x leverage. SetHoldings("SPY", 1); // debug message to your console. Time is the algorithm time. // send longer messages to a file - these are capped to 10kb Debug("Purchased SPY on " + Time.ToShortDateString()); //Log("This is a longer message send to log."); } }
/// <summary> /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. /// </summary> public void OnData(TradeBars data) { foreach (var symbol in _symbols.Where(s => data.ContainsKey(s))) { //Create a trading asset package for each symbol _vwaps[symbol].Update(data[symbol]); //_tradingAssets[symbol].Scan(data[symbol]); } }
public void OnData(TradeBars data) { if (!Portfolio.HoldStock && data.ContainsKey("AAPL")) { int quantity = (int)Math.Floor(Portfolio.Cash / data["AAPL"].Close); Order("AAPL", quantity); Debug("Purchased SPY on " + Time.ToShortDateString()); Notify.Email("*****@*****.**", "Test", "Test Body", "test attachment"); } }
/// <summary> /// Raises the data event. /// </summary> /// <param name="data">Data.</param> public void OnData(TradeBars data) { if (!Portfolio.HoldStock && data.ContainsKey("AAPL")) { int quantity = (int)Math.Floor(Portfolio.Cash / data["AAPL"].Close); Order("AAPL", quantity); Debug("Purchased SPY on " + Time.ToShortDateString()); Notify.Email("*****@*****.**", "Test", "Test Body", "test attachment"); } }
private void UpdateBars(TradeBars data) { foreach (var bar in data.Values) { if (!_bars.ContainsKey(bar.Symbol)) { _bars.Add(bar.Symbol, bar); } _bars[bar.Symbol] = bar; } }
/// <summary> /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. /// </summary> /// <param name="data">Slice object keyed by symbol containing the stock data</param> public void OnData(TradeBars data) { TradeBar currentBar = data [Symbol]; if (!data.ContainsKey (Symbol)) return; _tradeBars.Add (currentBar); if (!_tradeBars.IsReady) return; if (!ema.IsReady) return; _emaValues.Add (ema.Current.Value); if (_emaValues.Count > 10) _emaValues.RemoveAt (0); var slope = 0m; if (_emaValues.Count > 2) { var xVals = new double[_emaValues.Count]; var yVals = new double[_emaValues.Count]; // load input data for regression for (int i = 0; i < _emaValues.Count; i++) { xVals [i] = i; // we want the log of our y values yVals [i] = (double)_emaValues [i]; } //http://numerics.mathdotnet.com/Regression.html // solves y=a + b*x via linear regression var fit = Fit.Line (xVals, yVals); var intercept = fit.Item1; slope = (decimal)fit.Item2; } var diff = currentBar.Close / ema.Current.Value - 1.0m; if (diff > 0.01m && slope > 0m) { if (!Portfolio[Symbol].Invested) { SetHoldings (Symbol, 1); Debug ("Purchased Stock"); } } else { Liquidate (Symbol); } }
/// <summary> /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. /// </summary> /// <param name="data">TradeBars IDictionary object with your stock data</param> public void OnData(TradeBars data) { if (!macd.IsReady) return; if (!data.ContainsKey("IBM")) return; if (lastAction.Date == Time.Date) return; lastAction = Time; var holding = Portfolio["SPY"]; if (holding.Quantity <= 0 && macd > macd.Signal && data["IBM"].Price > ema) { SetHoldings("IBM", 0.25m); } else if (holding.Quantity >= 0 && macd < macd.Signal && data["IBM"].Price < ema) { SetHoldings("IBM", -0.25m); } }
/// <summary> /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. /// </summary> /// <param name="data">Slice object keyed by symbol containing the stock data</param> public void OnData(TradeBars data) { if (!_rc.IsReady || !data.ContainsKey(_spy)) { return; } var value = data[_spy].Value; if (_holdings.Quantity <= 0 && value < _rc.LowerChannel) { SetHoldings(_spy, 1); Plot("Trade Plot", "Buy", value); } if (_holdings.Quantity >= 0 && value > _rc.UpperChannel) { SetHoldings(_spy, -1); Plot("Trade Plot", "Sell", value); } }
/******************************************************** * CLASS METHODS *********************************************************/ /// <summary> /// Launch the algorithm manager to run this strategy /// </summary> /// <param name="job">Algorithm job</param> /// <param name="algorithm">Algorithm instance</param> /// <param name="feed">Datafeed object</param> /// <param name="transactions">Transaction manager object</param> /// <param name="results">Result handler object</param> /// <param name="setup">Setup handler object</param> /// <param name="realtime">Realtime processing object</param> /// <remarks>Modify with caution</remarks> public static void Run(AlgorithmNodePacket job, IAlgorithm algorithm, IDataFeed feed, ITransactionHandler transactions, IResultHandler results, ISetupHandler setup, IRealTimeHandler realtime) { //Initialize: var backwardsCompatibilityMode = false; var tradebarsType = typeof (TradeBars); var ticksType = typeof(Ticks); var startingPerformance = setup.StartingCapital; var backtestMode = (job.Type == PacketType.BacktestNode); var methodInvokers = new Dictionary<Type, MethodInvoker>(); //Initialize Properties: _frontier = setup.StartingDate; _runtimeError = null; _algorithmId = job.AlgorithmId; _algorithmState = AlgorithmStatus.Running; _previousTime = setup.StartingDate.Date; //Create the method accessors to push generic types into algorithm: Find all OnData events: //Algorithm 1.0 Data Accessors. //If the users defined these methods, add them in manually. This allows keeping backwards compatibility to algorithm 1.0. var oldTradeBarsMethodInfo = (algorithm.GetType()).GetMethod("OnTradeBar", new[] { typeof(Dictionary<string, TradeBar>) }); var oldTicksMethodInfo = (algorithm.GetType()).GetMethod("OnTick", new[] { typeof(Dictionary<string, List<Tick>>) }); //Algorithm 2.0 Data Generics Accessors. //New hidden access to tradebars with custom type. var newTradeBarsMethodInfo = (algorithm.GetType()).GetMethod("OnData", new[] { tradebarsType }); var newTicksMethodInfo = (algorithm.GetType()).GetMethod("OnData", new[] { ticksType }); if (newTradeBarsMethodInfo == null && newTicksMethodInfo == null) { backwardsCompatibilityMode = true; if (oldTradeBarsMethodInfo != null) methodInvokers.Add(tradebarsType, oldTradeBarsMethodInfo.DelegateForCallMethod()); if (oldTradeBarsMethodInfo != null) methodInvokers.Add(ticksType, oldTicksMethodInfo.DelegateForCallMethod()); } else { backwardsCompatibilityMode = false; if (newTradeBarsMethodInfo != null) methodInvokers.Add(tradebarsType, newTradeBarsMethodInfo.DelegateForCallMethod()); if (newTicksMethodInfo != null) methodInvokers.Add(ticksType, newTicksMethodInfo.DelegateForCallMethod()); } //Go through the subscription types and create invokers to trigger the event handlers for each custom type: foreach (var config in feed.Subscriptions) { //If type is a tradebar, combine tradebars and ticks into unified array: if (config.Type.Name != "TradeBar" && config.Type.Name != "Tick") { //Get the matching method for this event handler - e.g. public void OnData(Quandl data) { .. } var genericMethod = (algorithm.GetType()).GetMethod("OnData", new[] { config.Type }); //Is we already have this Type-handler then don't add it to invokers again. if (methodInvokers.ContainsKey(config.Type)) continue; //If we couldnt find the event handler, let the user know we can't fire that event. if (genericMethod == null) { _runtimeError = new Exception("Data event handler not found, please create a function matching this template: public void OnData(" + config.Type.Name + " data) { }"); _algorithmState = AlgorithmStatus.RuntimeError; return; } methodInvokers.Add(config.Type, genericMethod.DelegateForCallMethod()); } } //Loop over the queues: get a data collection, then pass them all into relevent methods in the algorithm. Log.Debug("AlgorithmManager.Run(): Algorithm initialized, launching time loop."); foreach (var newData in DataStream.GetData(feed, setup.StartingDate)) { //Check this backtest is still running: if (_algorithmState != AlgorithmStatus.Running) break; //Go over each time stamp we've collected, pass it into the algorithm in order: foreach (var time in newData.Keys) { //Set the time frontier: _frontier = time; //Execute with TimeLimit Monitor: if (Isolator.IsCancellationRequested) return; //Refresh the realtime event monitor: realtime.SetTime(time); //Fire EOD if the time packet we just processed is greater if (backtestMode && _previousTime.Date != time.Date) { //Sample the portfolio value over time for chart. results.SampleEquity(_previousTime, Math.Round(algorithm.Portfolio.TotalPortfolioValue, 4)); if (startingPerformance == 0) { results.SamplePerformance(_previousTime.Date, 0); } else { results.SamplePerformance(_previousTime.Date, Math.Round((algorithm.Portfolio.TotalPortfolioValue - startingPerformance) * 100 / startingPerformance, 10)); } startingPerformance = algorithm.Portfolio.TotalPortfolioValue; } //Check if the user's signalled Quit: loop over data until day changes. if (algorithm.GetQuit()) { _algorithmState = AlgorithmStatus.Quit; break; } //Pass in the new time first: algorithm.SetDateTime(time); //Trigger the data events: Invoke the types we have data for: var oldBars = new Dictionary<string, TradeBar>(); var oldTicks = new Dictionary<string, List<Tick>>(); var newBars = new TradeBars(time); var newTicks = new Ticks(time); //Invoke all non-tradebars, non-ticks methods: // --> i == Subscription Configuration Index, so we don't need to compare types. foreach (var i in newData[time].Keys) { //Data point and config of this point: var dataPoints = newData[time][i]; var config = feed.Subscriptions[i]; //Create TradeBars Unified Data --> OR --> invoke generic data event. One loop. foreach (var dataPoint in dataPoints) { //Update the securities properties: first before calling user code to avoid issues with data algorithm.Securities.Update(time, dataPoint); //Update registered consolidators for this symbol index for (var j = 0; j < config.Consolidators.Count; j++) { config.Consolidators[j].Update(dataPoint); } switch (config.Type.Name) { case "TradeBar": var bar = dataPoint as TradeBar; try { if (bar != null) { if (backwardsCompatibilityMode) { if (!oldBars.ContainsKey(bar.Symbol)) oldBars.Add(bar.Symbol, bar); } else { if (!newBars.ContainsKey(bar.Symbol)) newBars.Add(bar.Symbol, bar); } } } catch (Exception err) { Log.Error(time.ToLongTimeString() + " >> " + bar.Time.ToLongTimeString() + " >> " + bar.Symbol + " >> " + bar.Value.ToString("C")); Log.Error("AlgorithmManager.Run(): Failed to add TradeBar (" + bar.Symbol + ") Time: (" + time.ToLongTimeString() + ") Count:(" + newBars.Count + ") " + err.Message); } break; case "Tick": var tick = dataPoint as Tick; if (tick != null) { if (backwardsCompatibilityMode) { if (!oldTicks.ContainsKey(tick.Symbol)) { oldTicks.Add(tick.Symbol, new List<Tick>()); } oldTicks[tick.Symbol].Add(tick); } else { if (!newTicks.ContainsKey(tick.Symbol)) { newTicks.Add(tick.Symbol, new List<Tick>()); } newTicks[tick.Symbol].Add(tick); } } break; default: //Send data into the generic algorithm event handlers try { methodInvokers[config.Type](algorithm, dataPoint); } catch (Exception err) { _runtimeError = err; _algorithmState = AlgorithmStatus.RuntimeError; Log.Debug("AlgorithmManager.Run(): RuntimeError: Custom Data: " + err.Message + " STACK >>> " + err.StackTrace); return; } break; } } } //After we've fired all other events in this second, fire the pricing events: if (backwardsCompatibilityMode) { //Log.Debug("AlgorithmManager.Run(): Invoking v1.0 Event Handlers..."); try { if (oldTradeBarsMethodInfo != null && oldBars.Count > 0) methodInvokers[tradebarsType](algorithm, oldBars); if (oldTicksMethodInfo != null && oldTicks.Count > 0) methodInvokers[ticksType](algorithm, oldTicks); } catch (Exception err) { _runtimeError = err; _algorithmState = AlgorithmStatus.RuntimeError; Log.Debug("AlgorithmManager.Run(): RuntimeError: Backwards Compatibility Mode: " + err.Message + " STACK >>> " + err.StackTrace); return; } } else { //Log.Debug("AlgorithmManager.Run(): Invoking v2.0 Event Handlers..."); try { if (newTradeBarsMethodInfo != null && newBars.Count > 0) methodInvokers[tradebarsType](algorithm, newBars); if (newTicksMethodInfo != null && newTicks.Count > 0) methodInvokers[ticksType](algorithm, newTicks); } catch (Exception err) { _runtimeError = err; _algorithmState = AlgorithmStatus.RuntimeError; Log.Debug("AlgorithmManager.Run(): RuntimeError: New Style Mode: " + err.Message + " STACK >>> " + err.StackTrace); return; } } //If its the historical/paper trading models, wait until market orders have been "filled" // Manually trigger the event handler to prevent thread switch. transactions.ProcessSynchronousEvents(); //Save the previous time for the sample calculations _previousTime = time; } // End of Time Loop // Process any required events of the results handler such as sampling assets, equity, or stock prices. results.ProcessSynchronousEvents(); } // End of ForEach DataStream //Stream over:: Send the final packet and fire final events: Log.Trace("AlgorithmManager.Run(): Firing On End Of Algorithm..."); try { algorithm.OnEndOfAlgorithm(); } catch (Exception err) { _algorithmState = AlgorithmStatus.RuntimeError; _runtimeError = new Exception("Error running OnEndOfAlgorithm(): " + err.Message, err.InnerException); Log.Debug("AlgorithmManager.OnEndOfAlgorithm(): " + err.Message + " STACK >>> " + err.StackTrace); return; } // Process any required events of the results handler such as sampling assets, equity, or stock prices. results.ProcessSynchronousEvents(forceProcess: true); //Liquidate Holdings for Calculations: if (_algorithmState == AlgorithmStatus.Liquidated || !Engine.LiveMode) { Log.Trace("AlgorithmManager.Run(): Liquidating algorithm holdings..."); algorithm.Liquidate(); results.LogMessage("Algorithm Liquidated"); results.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.Liquidated); } //Manually stopped the algorithm if (_algorithmState == AlgorithmStatus.Stopped) { Log.Trace("AlgorithmManager.Run(): Stopping algorithm..."); results.LogMessage("Algorithm Stopped"); results.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.Stopped); } //Backtest deleted. if (_algorithmState == AlgorithmStatus.Deleted) { Log.Trace("AlgorithmManager.Run(): Deleting algorithm..."); results.DebugMessage("Algorithm Id:(" + job.AlgorithmId + ") Deleted by request."); results.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.Deleted); } //Algorithm finished, send regardless of commands: results.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.Completed); //Take final samples: results.SampleRange(algorithm.GetChartUpdates()); results.SampleEquity(_frontier, Math.Round(algorithm.Portfolio.TotalPortfolioValue, 4)); results.SamplePerformance(_frontier, Math.Round((algorithm.Portfolio.TotalPortfolioValue - startingPerformance) * 100 / startingPerformance, 10)); }
/******************************************************** * CLASS METHODS *********************************************************/ /// <summary> /// Launch the algorithm manager to run this strategy /// </summary> /// <param name="job">Algorithm job</param> /// <param name="algorithm">Algorithm instance</param> /// <param name="feed">Datafeed object</param> /// <param name="transactions">Transaction manager object</param> /// <param name="results">Result handler object</param> /// <param name="setup">Setup handler object</param> /// <param name="realtime">Realtime processing object</param> /// <remarks>Modify with caution</remarks> public static void Run(AlgorithmNodePacket job, IAlgorithm algorithm, IDataFeed feed, ITransactionHandler transactions, IResultHandler results, ISetupHandler setup, IRealTimeHandler realtime) { //Initialize: var backwardsCompatibilityMode = false; var tradebarsType = typeof(TradeBars); var ticksType = typeof(Ticks); var startingPerformance = setup.StartingCapital; var backtestMode = (job.Type == PacketType.BacktestNode); var methodInvokers = new Dictionary <Type, MethodInvoker>(); //Initialize Properties: _frontier = setup.StartingDate; _runtimeError = null; _algorithmId = job.AlgorithmId; _algorithmState = AlgorithmStatus.Running; _previousTime = setup.StartingDate.Date; //Create the method accessors to push generic types into algorithm: Find all OnData events: //Algorithm 1.0 Data Accessors. //If the users defined these methods, add them in manually. This allows keeping backwards compatibility to algorithm 1.0. var oldTradeBarsMethodInfo = (algorithm.GetType()).GetMethod("OnTradeBar", new[] { typeof(Dictionary <string, TradeBar>) }); var oldTicksMethodInfo = (algorithm.GetType()).GetMethod("OnTick", new[] { typeof(Dictionary <string, List <Tick> >) }); //Algorithm 2.0 Data Generics Accessors. //New hidden access to tradebars with custom type. var newTradeBarsMethodInfo = (algorithm.GetType()).GetMethod("OnData", new[] { tradebarsType }); var newTicksMethodInfo = (algorithm.GetType()).GetMethod("OnData", new[] { ticksType }); if (newTradeBarsMethodInfo == null && newTicksMethodInfo == null) { backwardsCompatibilityMode = true; if (oldTradeBarsMethodInfo != null) { methodInvokers.Add(tradebarsType, oldTradeBarsMethodInfo.DelegateForCallMethod()); } if (oldTradeBarsMethodInfo != null) { methodInvokers.Add(ticksType, oldTicksMethodInfo.DelegateForCallMethod()); } } else { backwardsCompatibilityMode = false; if (newTradeBarsMethodInfo != null) { methodInvokers.Add(tradebarsType, newTradeBarsMethodInfo.DelegateForCallMethod()); } if (newTicksMethodInfo != null) { methodInvokers.Add(ticksType, newTicksMethodInfo.DelegateForCallMethod()); } } //Go through the subscription types and create invokers to trigger the event handlers for each custom type: foreach (var config in feed.Subscriptions) { //If type is a tradebar, combine tradebars and ticks into unified array: if (config.Type.Name != "TradeBar" && config.Type.Name != "Tick") { //Get the matching method for this event handler - e.g. public void OnData(Quandl data) { .. } var genericMethod = (algorithm.GetType()).GetMethod("OnData", new[] { config.Type }); //Is we already have this Type-handler then don't add it to invokers again. if (methodInvokers.ContainsKey(config.Type)) { continue; } //If we couldnt find the event handler, let the user know we can't fire that event. if (genericMethod == null) { _runtimeError = new Exception("Data event handler not found, please create a function matching this template: public void OnData(" + config.Type.Name + " data) { }"); _algorithmState = AlgorithmStatus.RuntimeError; return; } methodInvokers.Add(config.Type, genericMethod.DelegateForCallMethod()); } } //Loop over the queues: get a data collection, then pass them all into relevent methods in the algorithm. Log.Debug("AlgorithmManager.Run(): Algorithm initialized, launching time loop."); foreach (var newData in DataStream.GetData(feed, setup.StartingDate)) { //Check this backtest is still running: if (_algorithmState != AlgorithmStatus.Running) { break; } //Go over each time stamp we've collected, pass it into the algorithm in order: foreach (var time in newData.Keys) { //Set the time frontier: _frontier = time; //Execute with TimeLimit Monitor: if (Isolator.IsCancellationRequested) { return; } //Refresh the realtime event monitor: realtime.SetTime(time); //Fire EOD if the time packet we just processed is greater if (backtestMode && _previousTime.Date != time.Date) { //Sample the portfolio value over time for chart. results.SampleEquity(_previousTime, Math.Round(algorithm.Portfolio.TotalPortfolioValue, 4)); if (startingPerformance == 0) { results.SamplePerformance(_previousTime.Date, 0); } else { results.SamplePerformance(_previousTime.Date, Math.Round((algorithm.Portfolio.TotalPortfolioValue - startingPerformance) * 100 / startingPerformance, 10)); } startingPerformance = algorithm.Portfolio.TotalPortfolioValue; } //Check if the user's signalled Quit: loop over data until day changes. if (algorithm.GetQuit()) { _algorithmState = AlgorithmStatus.Quit; break; } //Pass in the new time first: algorithm.SetDateTime(time); //Trigger the data events: Invoke the types we have data for: var oldBars = new Dictionary <string, TradeBar>(); var oldTicks = new Dictionary <string, List <Tick> >(); var newBars = new TradeBars(time); var newTicks = new Ticks(time); //Invoke all non-tradebars, non-ticks methods: // --> i == Subscription Configuration Index, so we don't need to compare types. foreach (var i in newData[time].Keys) { //Data point and config of this point: var dataPoints = newData[time][i]; var config = feed.Subscriptions[i]; //Create TradeBars Unified Data --> OR --> invoke generic data event. One loop. foreach (var dataPoint in dataPoints) { //Update the securities properties: first before calling user code to avoid issues with data algorithm.Securities.Update(time, dataPoint); //Update registered consolidators for this symbol index for (var j = 0; j < config.Consolidators.Count; j++) { config.Consolidators[j].Update(dataPoint); } switch (config.Type.Name) { case "TradeBar": var bar = dataPoint as TradeBar; try { if (bar != null) { if (backwardsCompatibilityMode) { if (!oldBars.ContainsKey(bar.Symbol)) { oldBars.Add(bar.Symbol, bar); } } else { if (!newBars.ContainsKey(bar.Symbol)) { newBars.Add(bar.Symbol, bar); } } } } catch (Exception err) { Log.Error(time.ToLongTimeString() + " >> " + bar.Time.ToLongTimeString() + " >> " + bar.Symbol + " >> " + bar.Value.ToString("C")); Log.Error("AlgorithmManager.Run(): Failed to add TradeBar (" + bar.Symbol + ") Time: (" + time.ToLongTimeString() + ") Count:(" + newBars.Count + ") " + err.Message); } break; case "Tick": var tick = dataPoint as Tick; if (tick != null) { if (backwardsCompatibilityMode) { if (!oldTicks.ContainsKey(tick.Symbol)) { oldTicks.Add(tick.Symbol, new List <Tick>()); } oldTicks[tick.Symbol].Add(tick); } else { if (!newTicks.ContainsKey(tick.Symbol)) { newTicks.Add(tick.Symbol, new List <Tick>()); } newTicks[tick.Symbol].Add(tick); } } break; default: //Send data into the generic algorithm event handlers try { methodInvokers[config.Type](algorithm, dataPoint); } catch (Exception err) { _runtimeError = err; _algorithmState = AlgorithmStatus.RuntimeError; Log.Error("AlgorithmManager.Run(): RuntimeError: Custom Data: " + err.Message + " STACK >>> " + err.StackTrace); return; } break; } } } //After we've fired all other events in this second, fire the pricing events: if (backwardsCompatibilityMode) { //Log.Debug("AlgorithmManager.Run(): Invoking v1.0 Event Handlers..."); try { if (oldTradeBarsMethodInfo != null && oldBars.Count > 0) { methodInvokers[tradebarsType](algorithm, oldBars); } if (oldTicksMethodInfo != null && oldTicks.Count > 0) { methodInvokers[ticksType](algorithm, oldTicks); } } catch (Exception err) { _runtimeError = err; _algorithmState = AlgorithmStatus.RuntimeError; Log.Error("AlgorithmManager.Run(): RuntimeError: Backwards Compatibility Mode: " + err.Message + " STACK >>> " + err.StackTrace); return; } } else { //Log.Debug("AlgorithmManager.Run(): Invoking v2.0 Event Handlers..."); try { if (newTradeBarsMethodInfo != null && newBars.Count > 0) { methodInvokers[tradebarsType](algorithm, newBars); } if (newTicksMethodInfo != null && newTicks.Count > 0) { methodInvokers[ticksType](algorithm, newTicks); } } catch (Exception err) { _runtimeError = err; _algorithmState = AlgorithmStatus.RuntimeError; Log.Error("AlgorithmManager.Run(): RuntimeError: New Style Mode: " + err.Message + " STACK >>> " + err.StackTrace); return; } } //If its the historical/paper trading models, wait until market orders have been "filled" // Manually trigger the event handler to prevent thread switch. transactions.ProcessSynchronousEvents(); //Save the previous time for the sample calculations _previousTime = time; } // End of Time Loop // Process any required events of the results handler such as sampling assets, equity, or stock prices. results.ProcessSynchronousEvents(); } // End of ForEach DataStream //Stream over:: Send the final packet and fire final events: Log.Trace("AlgorithmManager.Run(): Firing On End Of Algorithm..."); try { algorithm.OnEndOfAlgorithm(); } catch (Exception err) { _runtimeError = new Exception("Error running OnEndOfAlgorithm(): " + err.Message, err.InnerException); _algorithmState = AlgorithmStatus.RuntimeError; return; } // Process any required events of the results handler such as sampling assets, equity, or stock prices. results.ProcessSynchronousEvents(); //Liquidate Holdings for Calculations: if (_algorithmState == AlgorithmStatus.Liquidated || !Engine.LiveMode) { Log.Trace("AlgorithmManager.Run(): Liquidating algorithm holdings..."); algorithm.Liquidate(); results.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.Liquidated); } //Manually stopped the algorithm if (_algorithmState == AlgorithmStatus.Stopped) { Log.Trace("AlgorithmManager.Run(): Stopping algorithm..."); results.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.Stopped); } //Backtest deleted. if (_algorithmState == AlgorithmStatus.Deleted) { Log.Trace("AlgorithmManager.Run(): Deleting algorithm..."); results.DebugMessage("Algorithm Id:(" + job.AlgorithmId + ") Deleted by request."); results.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.Deleted); } //Algorithm finished, send regardless of commands: results.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.Completed); //Take final samples: results.SampleRange(algorithm.GetChartUpdates()); results.SampleEquity(_frontier, Math.Round(algorithm.Portfolio.TotalPortfolioValue, 4)); results.SamplePerformance(_frontier, Math.Round((algorithm.Portfolio.TotalPortfolioValue - startingPerformance) * 100 / startingPerformance, 10)); } // End of Run();
public void OnData(TradeBars data) { OrderSignal actualOrder = OrderSignal.doNothing; int i = 0; // just for logging foreach (string symbol in Symbols) { if (!data.ContainsKey(symbol) || !Strategy[symbol].IsReady) continue; bool breakCondition = (Time.Date == new DateTime(2015, 08, 07) || Time.Date == new DateTime(2015, 08, 10)) && isNormalOperativeTime && symbol == "MSFT"; if (isNormalOperativeTime) { actualOrder = Strategy[symbol].ActualSignal; } else if (noOvernight && isMarketAboutToClose) { actualOrder = CloseAllPositions(symbol); } ExecuteStrategy(symbol, actualOrder); #region Logging stuff - Filling the data StockLogging //Time,Close,Decycle,InvFisher,LightSmoothPrice,Momersion,PSAR,Position string newLine = string.Format("{0},{1},{2},{3},{4}", Time.ToString("u"), data[symbol].Close, Strategy[symbol].SmoothedSeries.Current.Value, PSARDict[symbol].Current.Value, Portfolio[symbol].Invested ? Portfolio[symbol].IsLong ? 1 : -1 : 0 ); stockLogging[i].AppendLine(newLine); i++; #endregion Logging stuff - Filling the data StockLogging } barCounter++; // just for logging }
/// <summary> /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. /// </summary> /// <param name="data">Slice object keyed by symbol containing the stock data</param> public void OnData(TradeBars data) { TradeBar currentBar = data [Symbol]; if (!data.ContainsKey(Symbol)) { return; } _tradeBars.Add(currentBar); if (!_tradeBars.IsReady) { return; } if (!ema.IsReady) { return; } _emaValues.Add(ema.Current.Value); if (_emaValues.Count > 10) { _emaValues.RemoveAt(0); } var slope = 0m; if (_emaValues.Count > 2) { var xVals = new double[_emaValues.Count]; var yVals = new double[_emaValues.Count]; // load input data for regression for (int i = 0; i < _emaValues.Count; i++) { xVals [i] = i; // we want the log of our y values yVals [i] = (double)_emaValues [i]; } //http://numerics.mathdotnet.com/Regression.html // solves y=a + b*x via linear regression var fit = Fit.Line(xVals, yVals); var intercept = fit.Item1; slope = (decimal)fit.Item2; } var diff = currentBar.Close / ema.Current.Value - 1.0m; if (diff > 0.01m && slope > 0m) { if (!Portfolio[Symbol].Invested) { SetHoldings(Symbol, 1); Debug("Purchased Stock"); } } else { Liquidate(Symbol); } }
public void OnData(TradeBars data) { foreach (var symbol in _symbols.Where(s => data.ContainsKey(s))) { _selectionDatas[symbol].Update(data[symbol], Portfolio[symbol].Quantity); Securities[symbol].IsTradable = true; } /*foreach (var symbol in _hedgeSymbols.Where(s => data.ContainsKey(s) && !Portfolio[s].Invested)) * { * Log("BUY >> " + symbol); * SetHoldings(symbol, FractionOfPortfolio); * }*/ if (IsWarmingUp) { return; } foreach (var symbol in _symbols.Where(s => Portfolio[s].Invested)) { var bullishToBearish = Portfolio[symbol].IsLong && _selectionDatas[symbol].TrendDirection == TrendSelectionData.Direction.Bearish; var bearishToBullish = Portfolio[symbol].IsShort && _selectionDatas[symbol].TrendDirection == TrendSelectionData.Direction.Bullish; var takeProfit = Portfolio[symbol].UnrealizedProfitPercent >= 0.3m; var stopLoss = Portfolio[symbol].UnrealizedProfitPercent < -0.1m; if (bullishToBearish || bearishToBullish || takeProfit || stopLoss) { Log("Flat >> " + Securities[symbol].Price + " Symbol " + symbol + " Profit: " + Portfolio[symbol].UnrealizedProfitPercent); //Liquidate(symbol); LimitOrder(symbol, -Portfolio[symbol].Quantity, data[symbol].Price); Securities[symbol].IsTradable = false; } } var trending = _selectionDatas .Where(kvp => kvp.Value.IsReady && Securities[kvp.Key].IsTradable) .Select(kvp => kvp) .ToList(); trending.Sort((a, b) => a.Value.CompareTo(b.Value)); var topTrending = trending.Take(NumberOfSymbols - Portfolio.Count); foreach (var security in topTrending) { if (security.Value.TrendDirection == TrendSelectionData.Direction.Bullish) { Log("Buy >> " + Securities[security.Key].Price + " Symbol " + security + " Profit: " + Portfolio[security.Key].UnrealizedProfitPercent); //SetHoldings(security.Key, FractionOfPortfolio); LimitOrder(security.Key, (int)(Portfolio.Cash / data[security.Key].Price), data[security.Key].Price); } else if (security.Value.TrendDirection == TrendSelectionData.Direction.Bearish) { Log("Sell >> " + Securities[security.Key].Price + " Symbol " + security + " Profit: " + Portfolio[security.Key].UnrealizedProfitPercent); //SetHoldings(security.Key, -FractionOfPortfolio); LimitOrder(security.Key, -(int)(Portfolio.Cash / data[security.Key].Price), data[security.Key].Price); } } Plot("ICH", "Price", data[_bench].Price); Plot("ICH", "SenkouA", _selectionDatas[_bench]._ich.SenkouA); Plot("ICH", "SenkouB", _selectionDatas[_bench]._ich.SenkouB); Plot("ICH", "ADX", _selectionDatas[_bench]._adx); Plot("ICH", "ADX.NegativeDirectionalIndex", _selectionDatas[_bench]._adx.NegativeDirectionalIndex); Plot("ICH", "ADX.PositiveDirectionalIndex", _selectionDatas[_bench]._adx.PositiveDirectionalIndex); }