public void OnData(TradeBars slice) { if (tradedToday.Date != Time.Date) { // leave a small buffer of cash var targetPercentage = 1m/(_todaysResponse.Securities.Count + 1); foreach (var target in _todaysResponse.Securities.Where(x => ValidSymbols.Contains(x.Ticker))) { // rebalance portfolio to equal weights SetHoldings(target.Ticker, targetPercentage); } tradedToday = Time.Date; } else { foreach (var target in _todaysResponse.Securities.Where(x => ValidSymbols.Contains(x.Ticker))) { // set stop loss / profit orders var security = Securities[target.Ticker]; if (!security.Invested) continue; if (security.Close < target.StopLoss || security.Close > target.StopGain) { MarketOrder(target.Ticker, -security.Holdings.Quantity, true); } } } }
/// <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) { // wait for our entire ribbon to be ready if (!_ribbon.All(x => x.IsReady)) return; // only once per day if (_previous.Date == Time.Date) return; Plot(Symbol, "Price", data[Symbol].Price); Plot(Symbol, _ribbon); // check for a buy signal var values = _ribbon.Select(x => x.Current.Value).ToArray(); var holding = Portfolio[Symbol]; if (holding.Quantity <= 0 && IsAscending(values)) { SetHoldings(Symbol, 1.0); } else if (holding.Quantity > 0 && IsDescending(values)) { Liquidate(Symbol); } _previous = Time; }
/// <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) { // only once per day if (previous.Date == data.Time.Date) return; if (!macd.IsReady) return; var holding = Portfolio[Symbol]; decimal signalDeltaPercent = (macd - macd.Signal)/macd.Fast; var tolerance = 0.0025m; // if our macd is greater than our signal, then let's go long if (holding.Quantity <= 0 && signalDeltaPercent > tolerance) // 0.01% { // longterm says buy as well SetHoldings(Symbol, 1.0); } // of our macd is less than our signal, then let's go short else if (holding.Quantity >= 0 && signalDeltaPercent < -tolerance) { Liquidate(Symbol); } // plot both lines Plot("MACD", macd, macd.Signal); Plot(Symbol, "Open", data[Symbol].Open); Plot(Symbol, macd.Fast, macd.Slow); previous = data.Time; }
// Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol. public void OnData(TradeBars data) { if (_vix == 0) return; if (Time.Date > _lastRebalance.Date.AddDays(5)) { //Rebalance every 5 days: _lastRebalance = Time; //Scale VIX fractionally 0-1 for 8-30. _deployedCapital = 1 - ((_vix - 8m) / 22m); //Don't allow negative scaling: if (_deployedCapital < -0.20m) _deployedCapital = -0.20m; //Fraction of capital preserved for bonds: _safeCapital = 1 - _deployedCapital; var tag = "Deployed: " + _deployedCapital.ToString("0.00") + " Safe: " + _safeCapital.ToString("0.00"); SetHoldings("SPY", _deployedCapital, true, tag); SetHoldings("IBM", _safeCapital - 0.01m, false, tag); // if (_scale > 0) // { // } // else if (Portfolio.Invested) // { // Liquidate(); // } } }
/// <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) { if (!Portfolio.Invested) { Order("SPY", (int)(Portfolio.Cash / data["SPY"].Close)); } }
/// <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); } }
public void OnData(TradeBars data) { if (Time - lastTradeTradeBars < tradeEvery) return; lastTradeTradeBars = Time; foreach (var kvp in data) { var symbol = kvp.Key; var bar = kvp.Value; if (bar.Time.RoundDown(bar.Period) != bar.Time) { // only trade on new data continue; } var holdings = Portfolio[symbol]; if (!holdings.Invested) { MarketOrder(symbol, 10); } else { MarketOrder(symbol, -holdings.Quantity); } } }
public void OnData(TradeBars data) { if (!Portfolio.Invested) { SetHoldings("SPY", 1); } }
public void OnData(TradeBars data) { //First Order, Set 50% MSFT: if (!Portfolio.Invested) { SetHoldings("MSFT", 0.5); step++; } if (Time.Date == new DateTime(2013, 7, 1) && step == 1) { SetHoldings("MSFT", 1); step++; } if (Time.Date == new DateTime(2013, 8, 1) && step == 2) { SetHoldings("IBM", 1, true); step++; } if (Time.Date == new DateTime(2013, 9, 3) && step == 3) { SetHoldings("IBM", -0.5, true); step++; } if (Time.Date == new DateTime(2013, 10, 1) && step == 4) { SetHoldings("SPY", -0.5); step++; } if (Time.Date == new DateTime(2013, 11, 1) && step == 5) { SetHoldings("IBM", -0.5, true); //Succeed. SetHoldings("SPY", -0.5); step++; } }
public void OnData(TradeBars data) { if (rsi.IsReady && mom.IsReady) { try { double signal = engine.DoInference((float)mom.Current.Value, (float)rsi.Current.Value); if (!Portfolio.Invested) { if (signal > 30) { int quantity = Decimal.ToInt32(Portfolio.Cash / data[symbol].Price); Buy(symbol, quantity); Debug("Purchased Stock: " + quantity + " shares"); } } else { if (signal < -10) { int quantity = Portfolio[symbol].Quantity; Sell(symbol, quantity); Debug("Sold Stock: " + quantity + " shares"); } } } catch (Exception ex) { Debug("Ex: " + ex.Message); Debug("## rsi: " + rsi + " mom: " + mom); } } }
/// <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) { foreach (string symbol in symbols) { Strategy[symbol].Add(data[symbol].Price); if (Strategy[symbol].IsReady() && ActualEMA[symbol].IsReady) { if (Strategy[symbol].Signal != 0) { decimal prevOscilator = Strategy[symbol].PreviousLaguerre - PreviousEMA[symbol]; decimal actualOscilator = Strategy[symbol].ActualLaguerre - ActualEMA[symbol]; bool longSignal = prevOscilator - tolerance > 0 && actualOscilator + tolerance < 0; bool shortSignal = prevOscilator + tolerance < 0 && actualOscilator - tolerance > 0; double signal = 0; if (longSignal) signal = 1; if (shortSignal) signal = -1; if (!Portfolio[symbol].HoldStock) { SetHoldings(symbol, signal * 0.25); } else { if (Portfolio[symbol].IsLong && shortSignal) Liquidate(symbol); if (Portfolio[symbol].IsShort && longSignal) Liquidate(symbol); } } } PreviousEMA[symbol] = ActualEMA[symbol].Current.Price; } }
/// <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) { barcount++; var time = this.Time; hma7.Update(time, data[symbol].Close); hma14.Update(time, data[symbol].Close); hma28.Update(time, data[symbol].Close); Price.Add(idp(time, data[symbol].Close)); UpdateInstantTrend(time); if (hma28.IsReady) { string logmsg = string.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10}", this.Time, barcount, data[symbol].Open, data[symbol].High, data[symbol].Low, data[symbol].Close, hma7.Current.Value, hma14.Current.Value, hma28.Current.Value, instantTrend[0].Value, ""); mylog.Debug(logmsg); } }
/// <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 (lastAction.Date == Time.Date) return; if (!Portfolio.Invested) { SetHoldings("SPY", 0.5); lastAction = Time; } if (Time.DayOfWeek == DayOfWeek.Tuesday) { AddSecurity(SecurityType.Equity, "AIG"); AddSecurity(SecurityType.Equity, "BAC"); lastAction = Time; } else if (Time.DayOfWeek == DayOfWeek.Wednesday) { SetHoldings("AIG", .25); SetHoldings("BAC", .25); lastAction = Time; } else if (Time.DayOfWeek == DayOfWeek.Thursday) { RemoveSecurity("BAC"); RemoveSecurity("AIG"); lastAction = Time; } }
public void OnData(TradeBars data) { bool isMarketAboutToClose = !theMarket.DateTimeIsOpen(Time.AddMinutes(10)); OrderSignal actualOrder = OrderSignal.doNothing; int i = 0; foreach (string symbol in Symbols) { // Operate only if the market is open if (theMarket.DateTimeIsOpen(Time)) { // First check if there are some limit orders not filled yet. if (Transactions.LastOrderId > 0) { CheckLimitOrderStatus(symbol); } // Check if the market is about to close and noOvernight is true. if (noOvernight && isMarketAboutToClose) { actualOrder = ClosePositions(symbol); } else { // Now check if there is some signal and execute the strategy. actualOrder = Strategy[symbol].ActualSignal; } ExecuteStrategy(symbol, actualOrder); } } }
/// <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 (!Portfolio.Invested) { SetHoldings("MSFT", .5); Debug("Purchased Stock"); } }
//Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol. public void OnData(TradeBars data) { if (!Portfolio.HoldStock) { Order("MSFT", (int)Math.Floor(Portfolio.Cash / data["MSFT"].Close) ); Debug("Debug Purchased MSFT"); } }
/// <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 (!Portfolio.Invested) { SetHoldings("SPY", .75); // leave some room lest we experience a margin call! Debug("Purchased Stock"); } }
//Data Event Handler: New data arrives here. Upload Data "TradeBars" type is a dictionary of strings so you can access it by symbol. public void OnData(TradeBars data) { string display = ""; foreach (var bar in data.Values) { display += ">> " + bar.Symbol + ": " + bar.Value.ToString("C"); } Debug("ALGO>> OnData(TradeBar) >> " + Time.ToString() + " >> " + data.Count + " >> " + display); }
/// <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"); } }
/// <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); } }
/// <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 (Transactions.OrdersCount == 0) { SetHoldings("MSFT", .5); // place some orders that won't fill, when the split comes in they'll get modified to reflect the split Debug("Purchased Stock: " + Securities["MSFT"].Price); StopMarketOrder("MSFT", -CalculateOrderQuantity("MSFT", .25), data["MSFT"].Low/2); LimitOrder("MSFT", -CalculateOrderQuantity("MSFT", .25), data["MSFT"].High*2); } }
public void OnData(TradeBars data) { if (PSARList[0].IsReady && PSARList[1].IsReady && PSARList[2].IsReady) { decimal test = (PSARList[1].Current.Value / PSARList[0].Current.Value == 1m) && (PSARList[2].Current.Value / PSARList[0].Current.Value == 1m) ? 1m : 0m; testerAcum = testerAcum + test; counter++; } }
public void OnData(TradeBars data) { if (!Portfolio[symbol].Invested) { SetHoldings(symbol, 1); } logResult.AppendLine(string.Format("{0},{1},{2},{3}", Time.ToString("u"), data[symbol].Close, LSMA.Current.Value, LSMA.IsReady )); }
public void OnData(TradeBars data) { // wait for our indicators to ready if (!Fast.IsReady || !Slow.IsReady) return; if (Fast > Slow*1.001m) { SetHoldings("SPY", 1); } else if (Fast < Slow*0.999m) { Liquidate("SPY"); } }
/// <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 (Time.Date != last.Date) // each morning submit a market on open order { submittedMarketOnCloseToday = false; MarketOnOpenOrder("SPY", 100); last = Time; } if (!submittedMarketOnCloseToday && security.Exchange.ExchangeOpen) // once the exchange opens submit a market on close order { submittedMarketOnCloseToday = true; MarketOnCloseOrder("SPY", -100); } }
/// <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) { try { // the first time we come through here we'll need to do some things such as allocation // and initializing our symbol data if (first) { first = false; LastRotationTime = Time; return; } var delta = Time.Subtract(LastRotationTime); if (delta > RotationInterval) { LastRotationTime = Time; // pick which one is best from growth and safety symbols var orderedObjScores = SymbolData.OrderByDescending(x => x.ObjectiveScore).ToList(); foreach (var orderedObjScore in orderedObjScores) { Log(">>SCORE>>" + orderedObjScore.Symbol + ">>" + orderedObjScore.ObjectiveScore); } var bestGrowth = orderedObjScores.First(); if (bestGrowth.ObjectiveScore > 0) { if (Portfolio[bestGrowth.Symbol].Quantity == 0) { Log("PREBUY>>LIQUIDATE>>"); Liquidate(); } Log(">>BUY>>" + bestGrowth.Symbol + "@" + (100 * bestGrowth.OneMonthPerformance).ToString("00.00")); decimal qty = Portfolio.Cash / Securities[bestGrowth.Symbol].Close; MarketOrder(bestGrowth.Symbol, (int) qty); } else { // if no one has a good objective score then let's hold cash this month to be safe Log(">>LIQUIDATE>>CASH"); Liquidate(); } } } catch (Exception ex) { Error("OnTradeBar: " + ex.Message + "\r\n\r\n" + ex.StackTrace); } }
/// <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); } }
// Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol. public void OnData(TradeBars data) { //Rebalance once per day: if (Time.Date > _lastRebalance.Date.AddDays(5)) { if (_scale > 0) { SetHoldings("SPY", _scale, false, "Scale: " + _scale); } else { Liquidate(); } _lastRebalance = Time; } }
public void OnData(TradeBars data) { // wait for our indicators to ready if (!Fast.IsReady || !Slow.IsReady) { return; } if (Fast > Slow * 1.001m) { SetHoldings("SPY", 1); } else if (Fast < Slow * 0.999m) { Liquidate("SPY"); } }
/// <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) { foreach (string symbol in symbols) { if (!hma[symbol].IsReady) { return; } Strategy[symbol].AddSerieValue(Time, hma[symbol]); isMarketOpen = Market.DateTimeIsOpen(Time) && Market.DateTimeIsOpen(Time.AddMinutes(10)); if (isMarketOpen) { if (Strategy[symbol].IsReady) { // If I have stocks and there's a turn around, then liquidate if (Portfolio[symbol].HoldStock && Strategy[symbol].TurnAround) { Liquidate(symbol); } // If I don't have stocks and there's a signal, then operate. else if (!Portfolio[symbol].HoldStock && Strategy[symbol].OrderSignal != 0) { EntryAndSetStopLoss(symbol, Strategy[symbol].OrderSignal); } } } // If have stocks and the market is about ot close (15 minutes earlier), liquidate. else if (Portfolio[symbol].HoldStock) { Liquidate(symbol); } } leverage = Portfolio.TotalHoldingsValue / Portfolio.TotalPortfolioValue; if (leverage > maxLeverageValue) { if (leverage > maxLeverage) { Log("Leverage exceeds max allowed leverage"); leverageBuffer *= 0.975m; } maxLeverageValue = leverage; } }
/// <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> /// Initializes a new instance of the <see cref="Slice"/> class /// </summary> /// <param name="time">The timestamp for this slice of data</param> /// <param name="data">The raw data in this slice</param> /// <param name="tradeBars">The trade bars for this slice</param> /// <param name="ticks">This ticks for this slice</param> /// <param name="splits">The splits for this slice</param> /// <param name="dividends">The dividends for this slice</param> /// <param name="delistings">The delistings for this slice</param> /// <param name="symbolChanges">The symbol changed events for this slice</param> public Slice(DateTime time, IEnumerable <BaseData> data, TradeBars tradeBars, Ticks ticks, Splits splits, Dividends dividends, Delistings delistings, SymbolChangedEvents symbolChanges) { Time = time; _dataByType = new Dictionary <Type, Lazy <object> >(); // market data _data = CreateDynamicDataDictionary(data); _ticks = CreateTicksCollection(ticks); _bars = CreateCollection <TradeBars, TradeBar>(tradeBars); // auxiliary data _splits = CreateCollection <Splits, Split>(splits); _dividends = CreateCollection <Dividends, Dividend>(dividends); _delistings = CreateCollection <Delistings, Delisting>(delistings); _symbolChangedEvents = CreateCollection <SymbolChangedEvents, SymbolChangedEvent>(symbolChanges); }
public void OnData(TradeBars data) { // wait for our indicators to ready if (!Fast.IsReady || !Slow.IsReady) { return; } if (Fast > Slow * 1.001m) { SetHoldings("SPY", 1); } else if (Portfolio["SPY"].HoldStock && Portfolio["SPY"].UnrealizedProfitPercent > Config.GetValue <decimal>("take", 0.2m)) { Liquidate("SPY"); } }
private void Strategy(TradeBars data) { if (Portfolio[symbol].IsLong) { nStatus = 1; } if (Portfolio[symbol].IsShort) { nStatus = -1; } /* * trend.Current.Value, * ema10.Current.Value,*/ List <int> ss = new List <int>(); ss.Add(Math.Sign(Price[0].Value)); ss.Add(Math.Sign(trendHistory[0].Value)); ss.Add(Math.Sign(emaHistory[0].Value)); ss.Add(Math.Sign(smaHistory[0].Value)); ss.Add(Math.Sign(Price[1].Value)); ss.Add(Math.Sign(trendHistory[1].Value)); ss.Add(Math.Sign(emaHistory[1].Value)); ss.Add(Math.Sign(smaHistory[1].Value)); if (barcount < 20) { return; } // SELL OUT AT THE EOD if (!SellOutEndOfDay(data)) { //if (barcount == 127) // Debug("here"); #region StrategyExecution // If we are seeking a top, and we are outside //TopBottomSeeker(data); TripleMovingAverageStrategy(); #endregion } sharesOwned = Portfolio[symbol].Quantity; }
/// <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) { foreach (string symbol in symbols) { Strategy[symbol].Add(data[symbol].Price); if (Strategy[symbol].IsReady() && ActualEMA[symbol].IsReady) { if (Strategy[symbol].Signal != 0) { decimal prevOscilator = Strategy[symbol].PreviousLaguerre - PreviousEMA[symbol]; decimal actualOscilator = Strategy[symbol].ActualLaguerre - ActualEMA[symbol]; bool longSignal = prevOscilator - tolerance > 0 && actualOscilator + tolerance < 0; bool shortSignal = prevOscilator + tolerance < 0 && actualOscilator - tolerance > 0; double signal = 0; if (longSignal) { signal = 1; } if (shortSignal) { signal = -1; } if (!Portfolio[symbol].HoldStock) { SetHoldings(symbol, signal * 0.25); } else { if (Portfolio[symbol].IsLong && shortSignal) { Liquidate(symbol); } if (Portfolio[symbol].IsShort && longSignal) { Liquidate(symbol); } } } } PreviousEMA[symbol] = ActualEMA[symbol].Current.Price; } }
/// <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) { // wait for our indicator to be ready if (!_macd.IsReady) { return; } var holding = Portfolio[_symbol]; var signalDeltaPercent = (_macd - _macd.Signal) / _macd.Fast; var tolerance = 0.0025m; // if our macd is greater than our signal, then let's go long if (holding.Quantity <= 0 && signalDeltaPercent > tolerance) { // 2. Call EmitInsights with insights created in correct direction, here we're going long // The EmitInsights method can accept multiple insights separated by commas EmitInsights( // Creates an insight for our symbol, predicting that it will move up within the fast ema period number of days Insight.Price(_symbol, TimeSpan.FromDays(FastEmaPeriod), InsightDirection.Up) ); // longterm says buy as well SetHoldings(_symbol, 1.0); } // if our macd is less than our signal, then let's go short else if (holding.Quantity >= 0 && signalDeltaPercent < -tolerance) { // 2. Call EmitInsights with insights created in correct direction, here we're going short // The EmitInsights method can accept multiple insights separated by commas EmitInsights( // Creates an insight for our symbol, predicting that it will move down within the fast ema period number of days Insight.Price(_symbol, TimeSpan.FromDays(FastEmaPeriod), InsightDirection.Down) ); // shortterm says sell as well SetHoldings(_symbol, -1.0); } // plot both lines Plot("MACD", _macd, _macd.Signal); Plot(_symbol, "Open", data[_symbol].Open); Plot(_symbol, _macd.Fast, _macd.Slow); }
/// <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) { barcount++; var time = this.Time; Price.Add(idp(time, data[symbol].Close)); cycleSignal.Add(idp(time, cycle.Current.Value)); //add last iteration value for the cycle cycle.Update(time, data[symbol].Close); diff.Add(idp(time, cycle.Current.Value - cycleSignal[0].Value)); fish.Update(idp(time, cycle.Current.Value)); standardDeviation.Update(idp(time, fish.Current.Value)); fishHistory.Add(idp(time, fish.Current.Value)); Strategy(data); //if (cycle.IsReady) //{ string logmsg = string.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},{16},{17},{18}", this.Time, barcount, data[symbol].Open, data[symbol].High, data[symbol].Low, data[symbol].Close, Price[0].Value, cycle.Current.Value, cycleSignal[0].Value, diff[0].Value, fish.Current.Value, //10 standardDeviation.Current.Value * factor, standardDeviation.Current.Value * -factor, fillprice, sharesOwned, tradeprofit, profit, fees, ""); mylog.Debug(logmsg); //} if (barcount == 50) { System.Diagnostics.Debug.WriteLine("here"); } }
/// <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 (!Portfolio.Invested) { //fails first several times, we'll keep decrementing until it succeeds SetHoldings("SPY", last); if (Portfolio["SPY"].Quantity == 0) { // each time we fail to purchase we'll decrease our set holdings percentage Debug(Time + " - Failed to purchase stock"); last *= 0.95m; } else { Debug(Time + " - Purchased Stock @ SetHoldings( " + last + " )"); } } }
public void OnData(TradeBars data) { var openOrders = Transactions.GetOpenOrders(_spy); if (openOrders.Count != 0) return; if (Time.Day > 10 && _security.Holdings.Quantity <= 0) { var quantity = CalculateOrderQuantity(_spy, .5m); Log("MarketOrder: " + quantity); MarketOrder(_spy, quantity, asynchronous: true); // async needed for partial fill market orders } else if (Time.Day > 20 && _security.Holdings.Quantity >= 0) { var quantity = CalculateOrderQuantity(_spy, -.5m); Log("MarketOrder: " + quantity); MarketOrder(_spy, quantity, asynchronous: true); // async needed for partial fill market orders } }
/// <summary> /// New Trade Bar Data Passed into TradeBar Event Handler: /// This method checks if the EMA's have crossed by at least a minimum magnitude. /// Having this minimum cross filters out noisy trade signals. /// </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) { //One data point per day: if (sampledToday.Date == data[symbol].Time.Date) { return; } //Only take one data point per day (opening price) var price = Securities[symbol].Close; sampledToday = data[symbol].Time; //Wait until EMA's are ready: if (!emaShort.Ready || !emaLong.Ready) { return; } //Get fresh cash balance: Set purchase quantity to equivalent 10% of portfolio. var holdings = Portfolio[symbol].Quantity; var quantity = Convert.ToInt32(Portfolio.Cash / price); if (holdings > 0 || holdings == 0) { //If we're long, or flat: check if EMA crossed negative: and crossed outside our safety margin: if ((emaShort.EMA * (1 + tolerance)) < emaLong.EMA) { //Now go short: Short-EMA signals a negative turn: reverse holdings Order(symbol, -(holdings + quantity)); Log(Time.ToShortDateString() + " > Go Short > Holdings: " + holdings.ToString() + " Quantity:" + quantity.ToString() + " Samples: " + emaShort.Samples); } } else if (holdings < 0 || holdings == 0) { //If we're short, or flat: check if EMA crossed positive: and crossed outside our safety margin: if ((emaShort.EMA * (1 - tolerance)) > emaLong.EMA) { //Now go long: Short-EMA crossed above long-EMA by sufficient margin Order(symbol, Math.Abs(holdings) + quantity); Log(Time.ToShortDateString() + "> Go Long > Holdings: " + holdings.ToString() + " Quantity:" + quantity.ToString() + " Samples: " + emaShort.Samples); } } }
/// <summary> /// Run the strategy associated with this algorithm /// </summary> /// <param name="data">TradeBars - the data received by the OnData event</param> private OrderSignal Strategy(TradeBars data) { #region "Strategy Execution" for (int i = 0; i < signals.Length; i++) { signals[i] = OrderSignal.doNothing; } // do not run the srategy after getting flat at the end of day if (SellOutEndOfDay(data)) { int tradesize = Convert.ToInt32(GetBetSize(symbol)); #region iTrendStrategy iTrendStrategy.Barcount = barcount; // for debugging // If we are holding stock, set the entry price for the strategy // the entry price is made absolute in the strategy to compare the the trigger if (Portfolio[symbol].HoldStock) { iTrendStrategy.nEntryPrice = Portfolio[symbol].HoldingsCost / Portfolio[symbol].AbsoluteQuantity; } // Run the strategy only to check the signal iTrendStrategy.maketrade = true; iTrendStrategy.SetTradesize(tradesize); signals[0] = iTrendStrategy.CheckSignal(data, trend.Current, out comment); #endregion // Execute only the selected strategy with it's signal //if(signals[LiveSignalIndex] != OrderSignal.doNothing) // ExecuteStrategy(symbol, signals[LiveSignalIndex], data); #region lists #endregion } #endregion return(signals[LiveSignalIndex]); }
/// <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) { // "TradeBars" object holds many "TradeBar" objects: it is a dictionary indexed by the symbol: // // e.g. data["MSFT"] data["GOOG"] //(!Portfolio.HoldStock) if (oldMACD == 0) { oldMACD = _macd.Signal; return; } if (first) { if (_macd.Signal >= oldMACD) { goingLong = true; first = false; goLong(data); return; } else if (_macd.Signal < oldMACD) { goingLong = false; first = false; goShort(data); return; } } else if ((_macd.Signal >= oldMACD) & goingLong == false) { goingLong = true; first = false; goLong(data); return; } else if ((_macd.Signal < oldMACD) & goingLong == true) { goingLong = false; first = false; goShort(data); return; } return; }
/// <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 (data == null) { throw new ArgumentNullException(nameof(data)); } // Log($"OnData() {Time}"); // only once per day if (_previous.Date == Time.Date) { return; } if (!_macd.IsReady) { return; } var holding = Portfolio[_symbol]; var signalDeltaPercent = _macd - _macd.Signal; var tolerance = 0m; // if our macd is greater than our signal, then let's go long if (holding.Quantity <= 0 && signalDeltaPercent > tolerance) // 0.01% { // longterm says buy as well SetHoldings(_forex.Symbol, 1.0); } // of our macd is less than our signal, then let's go short else if (holding.Quantity >= 0 && signalDeltaPercent < -tolerance) { SetHoldings(_forex.Symbol, -1.0); } // plot both lines Plot("MACD", _macd, _macd.Signal); Plot(_symbol, "Open", data[_symbol].Open); Plot(_symbol, _macd.Fast, _macd.Slow); _previous = Time; }
public bool SellOutEndOfDay(TradeBars data) { if (shouldSellOutAtEod) { if (this.Time.Hour == 15 && this.Time.Minute > 49 || this.Time.Hour == 16) { if (Portfolio[symbol].IsLong) { Sell(symbol, Portfolio[symbol].AbsoluteQuantity); } if (Portfolio[symbol].IsShort) { Buy(symbol, Portfolio[symbol].AbsoluteQuantity); } // Daily Profit #region logging if (this.Time.Hour == 16) { CalculateDailyProfits(); sharesOwned = Portfolio[symbol].Quantity; var _transactionsAsCsv = CsvSerializer.Serialize <OrderTransaction>(",", _transactions, true); StringBuilder sb = new StringBuilder(); foreach (string s in _transactionsAsCsv) { sb.AppendLine(s); } string attachment = sb.ToString(); Notify.Email("*****@*****.**", "Todays Trades " + this.Time.ToLongDateString(), "Number of Trades: " + _tradecount, attachment); SendTransactionsToFile(); _transactions = new List <OrderTransaction>(); } #endregion return(false); } } return(true); }
/// <summary> /// Run the strategy associated with this algorithm /// </summary> /// <param name="data">TradeBars - the data received by the OnData event</param> private string Strategy(TradeBars data) { #region "Strategy Execution" string ret = ""; if (SellOutEndOfDay(data)) { // if there were limit order tickets to cancel, wait a bar to execute the strategy iTrendStrategy.Barcount = barcount; // for debugging iTrendStrategy.nEntryPrice = nEntryPrice; signal = iTrendStrategy.ExecuteStrategy(data, tradesize, trend.Current, out comment); #region lists #endregion } #endregion return(ret); }
/// <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 (!_indicators.BB.IsReady || !_indicators.RSI.IsReady) { return; } _price = data[_symbol].Close; if (!Portfolio.HoldStock) { int quantity = (int)Math.Floor(Portfolio.Cash / _price); //Order function places trades: enter the string symbol and the quantity you want: Order(_symbol, quantity); //Debug sends messages to the user console: "Time" is the algorithm time keeper object Debug("Purchased SPY on " + Time.ToShortDateString()); } }
/// <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); } }
public void AccessesTradeBarAndQuoteBarForSameSymbol() { var tradeBar = new TradeBar(DateTime.Now, Symbols.BTCUSD, 3000, 3000, 3000, 3000, 100, Time.OneMinute); var quoteBar = new QuoteBar(DateTime.Now, Symbols.BTCUSD, new Bar(3100, 3100, 3100, 3100), 0, new Bar(3101, 3101, 3101, 3101), 0, Time.OneMinute); var tradeBars = new TradeBars { { Symbols.BTCUSD, tradeBar } }; var quoteBars = new QuoteBars { { Symbols.BTCUSD, quoteBar } }; var slice = new Slice(DateTime.Now, new BaseData[] { tradeBar, quoteBar }, tradeBars, quoteBars, null, null, null, null, null, null, null); var tradeBarData = slice.Get <TradeBar>(); Assert.AreEqual(1, tradeBarData.Count); Assert.AreEqual(3000, tradeBarData[Symbols.BTCUSD].Close); var quoteBarData = slice.Get <QuoteBar>(); Assert.AreEqual(1, quoteBarData.Count); Assert.AreEqual(3100, quoteBarData[Symbols.BTCUSD].Bid.Close); Assert.AreEqual(3101, quoteBarData[Symbols.BTCUSD].Ask.Close); slice = new Slice(DateTime.Now, new BaseData[] { tradeBar, quoteBar }); tradeBarData = slice.Get <TradeBar>(); Assert.AreEqual(1, tradeBarData.Count); Assert.AreEqual(3000, tradeBarData[Symbols.BTCUSD].Close); quoteBarData = slice.Get <QuoteBar>(); Assert.AreEqual(1, quoteBarData.Count); Assert.AreEqual(3100, quoteBarData[Symbols.BTCUSD].Bid.Close); Assert.AreEqual(3101, quoteBarData[Symbols.BTCUSD].Ask.Close); }
public OrderSignal CheckSignal(TradeBars data, Dictionary <string, string> paramlist, out string comment) { PropertyInfo[] properties = GetType().GetProperties(); // make sure symbol is set first for getting trendCurrent PropertyInfo s = properties.FirstOrDefault(x => x.Name == "symbol"); if (s != null) { symbol = new Symbol(paramlist["symbol"], paramlist["symbol"]); } IndicatorDataPoint trendCurrent = new IndicatorDataPoint(data[symbol].EndTime, 0);; string trend = paramlist["trend"]; trendCurrent.Value = System.Convert.ToDecimal(trend); foreach (var item in paramlist) { PropertyInfo p = properties.FirstOrDefault(x => x.Name == item.Key); if (p != null) { if (item.Key != "symbol") { { var converter = TypeDescriptor.GetConverter(p.PropertyType); var convertedvalue = converter.ConvertFrom(item.Value); var setmethod = p.SetMethod; if (setmethod != null) { p.SetValue(this, convertedvalue); } } } } } string current; OrderSignal retval = CheckSignal(data, trendCurrent, out current); comment = current; return(retval); }
/// <summary> /// Initializes a new instance of the <see cref="Slice"/> class /// </summary> /// <param name="time">The timestamp for this slice of data</param> /// <param name="data">The raw data in this slice</param> /// <param name="tradeBars">The trade bars for this slice</param> /// <param name="quoteBars">The quote bars for this slice</param> /// <param name="ticks">This ticks for this slice</param> /// <param name="optionChains">The option chains for this slice</param> /// <param name="futuresChains">The futures chains for this slice</param> /// <param name="splits">The splits for this slice</param> /// <param name="dividends">The dividends for this slice</param> /// <param name="delistings">The delistings for this slice</param> /// <param name="symbolChanges">The symbol changed events for this slice</param> /// <param name="hasData">true if this slice contains data</param> public Slice(DateTime time, IEnumerable <BaseData> data, TradeBars tradeBars, QuoteBars quoteBars, Ticks ticks, OptionChains optionChains, FuturesChains futuresChains, Splits splits, Dividends dividends, Delistings delistings, SymbolChangedEvents symbolChanges, bool?hasData = null) { Time = time; // market data _data = new Lazy <DataDictionary <SymbolData> >(() => CreateDynamicDataDictionary(data)); HasData = hasData ?? _data.Value.Count > 0; _ticks = ticks; _bars = tradeBars; _quoteBars = quoteBars; _optionChains = optionChains; _futuresChains = futuresChains; // auxiliary data _splits = splits; _dividends = dividends; _delistings = delistings; _symbolChangedEvents = symbolChanges; }
public void OnData(TradeBars data) { // wait for our indicators to ready if (!Fast.IsReady || !Slow.IsReady) { return; } if (!Portfolio["SPY"].HoldStock) { if (Fast > Slow * 1.001m) { SetHoldings("SPY", 1); } } else if (Portfolio["SPY"].UnrealizedProfitPercent > takeProfit || Portfolio["SPY"].UnrealizedProfitPercent < stopLoss) { Liquidate("SPY"); } }
public void OnData(TradeBars data) { OrderSignal actualOrder = OrderSignal.doNothing; int i = 0; // just for logging foreach (string symbol in Symbols) { if (isNormalOperativeTime) { ManageStopLoss(symbol); 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},{5},{6},{7}", Time.ToString("u"), data[symbol].Close, Strategy[symbol].DecycleTrend.Current.Value, Strategy[symbol].InverseFisher.Current.Value, Strategy[symbol].LightSmoothPrice.Current.Value, Strategy[symbol].Momersion.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">TradeBars dictionary object keyed by symbol containing the stock data</param> public void OnData(TradeBars data) { if (_changes == SecurityChanges.None) { return; } // liquidate securities removed from our universe foreach (var security in _changes.RemovedSecurities) { if (security.Invested) { Liquidate(security.Symbol); } } // we'll simply go long each security we added to the universe foreach (var security in _changes.AddedSecurities) { SetHoldings(security.Symbol, TargetPercent); } }
/// <summary> /// Initializes a new instance used by the <see cref="PythonSlice"/> /// </summary> /// <param name="slice">slice object to wrap</param> /// <remarks>This is required so that python slice enumeration works correctly since it relies on the private <see cref="_data"/> collection</remarks> protected Slice(Slice slice) { Time = slice.Time; _dataByType = slice._dataByType; _data = slice._data; HasData = slice.HasData; _ticks = slice._ticks; _bars = slice._bars; _quoteBars = slice._quoteBars; _optionChains = slice._optionChains; _futuresChains = slice._futuresChains; // auxiliary data _splits = slice._splits; _dividends = slice._dividends; _delistings = slice._delistings; _symbolChangedEvents = slice._symbolChangedEvents; }
/// <summary> /// Initializes a new instance of the <see cref="Slice"/> class /// </summary> /// <param name="time">The timestamp for this slice of data</param> /// <param name="data">The raw data in this slice</param> /// <param name="tradeBars">The trade bars for this slice</param> /// <param name="quoteBars">The quote bars for this slice</param> /// <param name="ticks">This ticks for this slice</param> /// <param name="optionChains">The option chains for this slice</param> /// <param name="splits">The splits for this slice</param> /// <param name="dividends">The dividends for this slice</param> /// <param name="delistings">The delistings for this slice</param> /// <param name="symbolChanges">The symbol changed events for this slice</param> /// <param name="hasData">true if this slice contains data</param> public Slice(DateTime time, IEnumerable <BaseData> data, TradeBars tradeBars, QuoteBars quoteBars, Ticks ticks, OptionChains optionChains, Splits splits, Dividends dividends, Delistings delistings, SymbolChangedEvents symbolChanges, bool?hasData = null) { Time = time; _dataByType = new Dictionary <Type, Lazy <object> >(); // market data _data = new Lazy <DataDictionary <SymbolData> >(() => CreateDynamicDataDictionary(data)); HasData = hasData ?? _data.Value.Count > 0; _ticks = CreateTicksCollection(ticks); _bars = CreateCollection <TradeBars, TradeBar>(tradeBars); _quoteBars = CreateCollection <QuoteBars, QuoteBar>(quoteBars); _optionChains = CreateCollection <OptionChains, OptionChain>(optionChains); // auxiliary data _splits = CreateCollection <Splits, Split>(splits); _dividends = CreateCollection <Dividends, Dividend>(dividends); _delistings = CreateCollection <Delistings, Delisting>(delistings); _symbolChangedEvents = CreateCollection <SymbolChangedEvents, SymbolChangedEvent>(symbolChanges); }
// Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol. public void OnData(TradeBars data) { if (_vix == 0) { return; } if (Time.Date > _lastRebalance.Date.AddDays(5)) { //Rebalance every 5 days: _lastRebalance = Time; //Scale VIX fractionally 0-1 for 8-30. _deployedCapital = 1 - ((_vix - 8m) / 22m); //Don't allow negative scaling: if (_deployedCapital < -0.20m) { _deployedCapital = -0.20m; } //Fraction of capital preserved for bonds: _safeCapital = 1 - _deployedCapital; var tag = "Deployed: " + _deployedCapital.ToString("0.00") + " Safe: " + _safeCapital.ToString("0.00"); SetHoldings("SPY", _deployedCapital, true, tag); SetHoldings("IBM", _safeCapital - 0.01m, false, tag); // if (_scale > 0) // { // } // else if (Portfolio.Invested) // { // Liquidate(); // } } }
public void OnData(TradeBars data) { var openOrders = Transactions.GetOpenOrders(_spy); if (openOrders.Count != 0) { return; } if (Time.Day > 10 && _security.Holdings.Quantity <= 0) { var quantity = CalculateOrderQuantity(_spy, .5m); Log("MarketOrder: " + quantity); MarketOrder(_spy, quantity, asynchronous: true); // async needed for partial fill market orders } else if (Time.Day > 20 && _security.Holdings.Quantity >= 0) { var quantity = CalculateOrderQuantity(_spy, -.5m); Log("MarketOrder: " + quantity); MarketOrder(_spy, quantity, asynchronous: true); // async needed for partial fill market orders } }
//Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol. public void OnData(TradeBars data) { _sss.Update(data["SPY"]); if (!_sss.IsReady) { return; } if (_sss > 80) { SetHoldings("SPY", -1m); } else if (_sss < 20) { SetHoldings("SPY", 1m); } else if (Portfolio["SPY"].UnrealizedProfitPercent > 0.05m) { Liquidate("SPY"); } }
public void OnData(TradeBars data) { channel.BasicConsume(queue: "backtest", autoAck: true, consumer: consumer); foreach (string element in equityList) { if (!Portfolio[element].Invested) { Order(element, 100); Debug("Purchased " + element + " on " + Time.ToShortDateString()); } } if (Time.Date != last.Date) // each morning submit a market on open order { _submittedMarketOnCloseToday = false; MarketOnOpenOrder("SPY", 100); last = Time; if (Portfolio.HoldStock) { return; } Order("SPY", 100); Debug("Purchased SPY on " + Time.ToShortDateString()); Sell("SPY", 50); Debug("Sell SPY on " + Time.ToShortDateString()); } if (!_submittedMarketOnCloseToday && _security.Exchange.ExchangeOpen) // once the exchange opens submit a market on close order { _submittedMarketOnCloseToday = true; MarketOnCloseOrder("SPY", -100); } }
/// <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) { // only once per day if (_previous.Date == Time.Date) { return; } if (!_macd.IsReady) { return; } var holding = Portfolio[_symbol]; var signalDeltaPercent = (_macd - _macd.Signal) / _macd.Fast; var tolerance = 0.0025m; // if our macd is greater than our signal, then let's go long if (holding.Quantity <= 0 && signalDeltaPercent > tolerance) // 0.01% { // longterm says buy as well SetHoldings(_symbol, 1.0); } // of our macd is less than our signal, then let's go short else if (holding.Quantity >= 0 && signalDeltaPercent < -tolerance) { Liquidate(_symbol); } // plot both lines Plot("MACD", _macd, _macd.Signal); Plot(_symbol, "Open", data[_symbol].Open); Plot(_symbol, _macd.Fast, _macd.Slow); _previous = Time; }