Crashed in OnTick with NullReferenceException: Object reference not set to an instance of an object.
Crashed in OnTick with NullReferenceException: Object reference not set to an instance of an object.
03 Sep 2020, 01:27
I'm trying to write a cBot, but when I went to backtest it, it came with an error; Crashed in OnTick with NullReferenceException: Object reference not set to an instance of an object.
If it helps, my code is:
using System;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.API.Requests;
using cAlgo.Indicators;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class NewcBot : Robot
{
#region User defined parameters
private MacdCrossOver _MACD;
private SimpleMovingAverage _Sma1;
[Parameter("Instance Name", DefaultValue = "Harrold")]
public string InstanceName { get; set; }
[Parameter("LotSize", DefaultValue = 0.1)]
public double LotSize { get; set; }
[Parameter("Period", DefaultValue = 9)]
public int Period { get; set; }
[Parameter("Long Cycle", DefaultValue = 26)]
public int LongCycle { get; set; }
[Parameter("Short Cycle", DefaultValue = 12)]
public int ShortCycle { get; set; }
[Parameter("Stop Loss", DefaultValue = 20)]
public int StopLoss { get; set; }
[Parameter("Take Profit", DefaultValue = 100)]
public int TakeProfit { get; set; }
[Parameter("Signal-line crossover true:if Signal-line crossover false: Zero crossover", DefaultValue = true)]
public bool IsSignalLineCrossover { get; set; }
[Parameter("Source EMA #1")]
public DataSeries SourceEma1 { get; set; }
[Parameter("Source EMA #2")]
public DataSeries SourceEma2 { get; set; }
[Parameter("Source EMA #3")]
public DataSeries SourceEma3 { get; set; }
[Parameter("Period EMA #1", DefaultValue = 79, MinValue = 1, MaxValue = 200)]
public int PeriodsEma1 { get; set; }
[Parameter("Period EMA #2", DefaultValue = 435, MinValue = 1, MaxValue = 500)]
public int PeriodsEma2 { get; set; }
[Parameter("Period EMA #3", DefaultValue = 30, MinValue = 1, MaxValue = 200)]
public int PeriodsEma3 { get; set; }
[Parameter("Calculate OnBar", DefaultValue = false)]
public bool CalculateOnBar { get; set; }
[Parameter("Trailing Stop Step (pips)", DefaultValue = 10)]
public int TrailingStopStep { get; set; }
[Parameter("Trailing Stop Trigger (in Pips)", DefaultValue = 10)]
public int TrailingStopTrigger { get; set; }
[Parameter("IncludeTrailingStop", DefaultValue = true)]
public bool IncludeTrailingStop { get; set; }
[Parameter("Include Break-Even", DefaultValue = true)]
public bool IncludeBreakEven { get; set; }
[Parameter("Break-Even Trigger (Pips)", DefaultValue = 5)]
public int BreakEvenPips { get; set; }
[Parameter("Break-Even Extra Pips", DefaultValue = 2, MinValue = 1)]
public int BreakEvenExtraPips { get; set; }
[Parameter("Source SMA #1")]
public DataSeries SourceSma1 { get; set; }
[Parameter("Period SMA #1", DefaultValue = 1)]
public int PeriodsSma1 { get; set; }
public double EntryPrice { get; set; }
public TradeResult TradeResult { get; set; }
public bool IsSuccesful { get; set; }
#endregion
#region Indicator declarations
private ExponentialMovingAverage _Ema1 { get; set; }
private ExponentialMovingAverage _Ema2 { get; set; }
private ExponentialMovingAverage _Ema3 { get; set; }
#endregion
#region cTrader events
/// This is called when the robot first starts, it is only called once.
protected override void OnStart()
{
// construct the indicators
_Ema1 = Indicators.ExponentialMovingAverage(SourceEma1, PeriodsEma1);
_Ema2 = Indicators.ExponentialMovingAverage(SourceEma2, PeriodsEma2);
_Ema3 = Indicators.ExponentialMovingAverage(SourceEma3, PeriodsEma3);
_MACD = Indicators.MacdCrossOver(LongCycle, ShortCycle, Period);
_Sma1 = Indicators.SimpleMovingAverage(SourceSma1, PeriodsSma1);
}
/// This method is called every time the price changes for the symbol
protected override void OnTick()
{
if (CalculateOnBar)
{
return;
}
ManagePositions();
if (IncludeTrailingStop)
{
SetTrailingStop();
}
if (IncludeBreakEven)
{
BreakEvenAdjustment();
}
}
/// This line is called at every candlebar close
protected override void OnBar()
{
if (!CalculateOnBar)
{
return;
}
ManagePositions();
}
#endregion
#region Position management
private void ManagePositions()
{
#region Open Position
#region Go Long
if (_Ema2.Result.Last(1) > _Ema2.Result.Last(2))
#endregion
#region Go Short
if (_Ema2.Result.Last(1) < _Ema2.Result.Last(2))
{
if (_Ema1.Result.Last(1) < _Ema1.Result.Last(2))
{
if (_Ema3.Result.Last(1) < _Ema3.Result.Last(2))
{
if (_MACD.MACD.Last(1) > _MACD.Histogram.Last(1))
{
if (IsSignalLineCrossover)
{
if (_MACD.MACD.Last(2) > _MACD.Signal.Last(2) && _MACD.MACD.Last(1) < _MACD.Signal.Last(1))
{
if (!IsPositionOpenByType(TradeType.Sell))
{
OpenPosition(TradeType.Sell);
}
ClosePosition(TradeType.Buy);
}
}
}
}
}
}
#endregion
#endregion
#region Close Position
#region Close Buy Position
if (_MACD.MACD.Last(2) > _MACD.Signal.Last(2) && _MACD.MACD.Last(1) < _MACD.Signal.Last(1))
{
if (_Sma1.Result.Last(1) > LastResult.Position.EntryPrice)
{
ClosePosition(TradeType.Buy);
}
if (_Sma1.Result.Last(1) > LastResult.Position.EntryPrice)
{
if (_Ema1.Result.Last(1) < _Ema1.Result.Last(2))
{
if (IsPositionOpenByType(TradeType.Buy))
{
ClosePosition(TradeType.Buy);
}
else
{
return;
}
}
}
}
#endregion
#region Close Sell Position
if (_MACD.MACD.Last(2) < _MACD.Signal.Last(2) && _MACD.MACD.Last(1) > _MACD.Signal.Last(1))
{
if (_Sma1.Result.Last(1) < LastResult.Position.EntryPrice)
{
ClosePosition(TradeType.Sell);
}
if (_Sma1.Result.Last(1) < LastResult.Position.EntryPrice)
{
if (_Ema1.Result.Last(1) > _Ema1.Result.Last(2))
{
if (IsPositionOpenByType(TradeType.Sell))
{
ClosePosition(TradeType.Sell);
}
else
{
return;
}
}
}
}
#endregion
#endregion
}
#region Order Execution
#region Execute Order - Buy
/// Opens a new long position
/// <param name="type"></param>
private void OpenPosition(TradeType type)
{
long volume = Symbol.QuantityToVolume(LotSize);
// open a new position
ExecuteMarketOrder(type, this.Symbol, volume, InstanceName, StopLoss, null);
}
#endregion
#region Execute Order _ Sell
/// <param name="type"></param>
private void ClosePosition(TradeType type)
{
var p = Positions.Find(InstanceName, this.Symbol, type);
if (p != null)
{
ClosePosition(p);
}
}
#endregion
#endregion
#endregion
#region Position Information
private bool IsPositionOpenByType(TradeType type)
{
var p = Positions.FindAll(InstanceName, Symbol, type);
if (p.Count() >= 1)
{
return true;
}
return false;
}
#endregion
#region Trailing Stop
/// <summary>
/// When the profit in pips is above or equal to Trigger the stop loss will start trailing the spot price.
/// TrailingStop defines the number of pips the Stop Loss trails the spot price by.
/// If Trigger is 0 trailing will begin immediately.
/// </summary>
private void SetTrailingStop()
{
var sellPositions = Positions.FindAll(InstanceName, Symbol, TradeType.Sell);
foreach (Position position in sellPositions)
{
double distance = position.EntryPrice - Symbol.Ask;
if (distance < TrailingStopTrigger * Symbol.PipSize)
continue;
double newStopLossPrice = Symbol.Ask + TrailingStopStep * Symbol.PipSize;
if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
{
ModifyPosition(position, newStopLossPrice, position.TakeProfit);
}
}
var buyPositions = Positions.FindAll(InstanceName, Symbol, TradeType.Buy);
foreach (Position position in buyPositions)
{
double distance = Symbol.Bid - position.EntryPrice;
if (distance < TrailingStopTrigger * Symbol.PipSize)
continue;
double newStopLossPrice = Symbol.Bid - TrailingStopStep * Symbol.PipSize;
if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
{
ModifyPosition(position, newStopLossPrice, position.TakeProfit);
}
}
}
#endregion
#region Break-Even
/// <summary>
/// Adjusts the break even plus (x) pips
/// </summary>
/// <param name="tradeType"></param>
private void BreakEvenAdjustment()
{
var allPositions = Positions.FindAll(InstanceName, Symbol);
foreach (Position position in allPositions)
{
if (position.StopLoss != null)
return;
var entryPrice = position.EntryPrice;
var distance = position.TradeType == TradeType.Buy ? Symbol.Bid - entryPrice : entryPrice - Symbol.Ask;
// move stop loss to break even plus and additional (x) pips
if (distance >= BreakEvenPips * Symbol.PipSize)
{
if (position.TradeType == TradeType.Buy)
{
if (position.StopLoss <= position.EntryPrice + (Symbol.PipSize * BreakEvenExtraPips) || position.StopLoss == null)
{
ModifyPosition(position, position.EntryPrice + (Symbol.PipSize * BreakEvenExtraPips), position.TakeProfit);
Print("Stop Loss to Break Even set for BUY position {0}", position.Id);
}
}
else
{
if (position.StopLoss >= position.EntryPrice - (Symbol.PipSize * BreakEvenExtraPips) || position.StopLoss == null)
{
ModifyPosition(position, entryPrice - (Symbol.PipSize * BreakEvenExtraPips), position.TakeProfit);
Print("Stop Loss to Break Even set for SELL position {0}", position.Id);
}
}
}
}
}
#endregion
}
}