I did some work on the Indicator (Heiken Ashi), and the Robot compiled successfully. However, I am still having a bit of issues. The Robot is not taking any trade whwn I did a backtest.
Can anyone help with how I may correct this problem. Please take a look at the codes for the Robot, and the Indicator, below:
1. Heiken Ashi cBot
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
namespace cAlgo
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class HeikinAshiBot : Robot
{
[Parameter("Label Perfix", DefaultValue = "HeikinAshiBot")]
public string labelPerfix { get; set; }
// Manage the trade
private void tradeManager(Position position)
{
if (position.TradeType == TradeType.Buy)
{
if (maBasedExit)
{
if (fastMa.Result.LastValue < slowMa.Result.LastValue)
ClosePosition(position);
}
if (macdBasedExit)
{
if (_macdHistogram.Histogram.Last(1) < 0)
ClosePosition(position);
}
if (exitOppositeCandle)
{
if (sameExit)
{
if (_heikenAshi.Open.Last(1) > _heikenAshi.Close.Last(1))
ClosePosition(position);
}
else if (position.TradeType == TradeType.Sell)
{
if (maBasedExit)
{
if (fastMa.Result.LastValue > slowMa.Result.LastValue)
ClosePosition(position);
}
if (macdBasedExit)
{
if (_macdHistogram.Histogram.Last(1) > 0)
ClosePosition(position);
}
if (exitOppositeCandle)
{
if (sameExit)
{
if (_heikenAshi.Open.Last(1) < _heikenAshi.Close.Last(1))
ClosePosition(position);
I need some help with this error CS1061. 'cAlgo.Indicators.HeikenAshi' does not contain a definition for 'Close' accepting a first argument of type 'cAlgo.Indicators.Heiken.Ashi' could be found (are you missing a using directive or an assembly reference?)
It is from the cBot published by "afhacker" version 2.1 "Heiken Ashi." However, whenever, I tried to compile the code, I get a "Build failed. Errors 22."
I used the Manage References in the context menu of the code to apply the 'Heiken Ashi' indicator to the code, but without any success.
Has anyone got this code working?
I would really appreciate your assistance. This is the original code which I downloaded from the Ctdn cBots portal.
using System;
using System.Linq;
using Microsoft.Win32;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
/*
Version 2.1
Developed by afhacker (Ahmad Noman Musleh)
Email : afhackermubasher@gmail.com
*/
namespace cAlgo
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.Registry)]
public class TMSBot : Robot
{
[Parameter("Scale In?", DefaultValue = false)]
public bool scaleIn { get; set; }
[Parameter("Scale In after:", DefaultValue = 1)]
public double scalePips { get; set; }
[Parameter("Contorl Scaled In Trades Volume?", DefaultValue = false)]
public bool scalePositionControl { get; set; }
[Parameter("Limit Scaling In?", DefaultValue = false)]
public bool limitScalingIn { get; set; }
[Parameter("Scale In #", DefaultValue = 2)]
public int scaleNumber { get; set; }
[Parameter("Mother Close?", DefaultValue = false)]
public bool motherClose { get; set; }
[Parameter("ATR Based SL", DefaultValue = true)]
public bool atrSl { get; set; }
[Parameter("ATR Periods", DefaultValue = 20)]
public int atrPeriod { get; set; }
[Parameter("ATR Multiplier", DefaultValue = 3)]
public int atrMultiplier { get; set; }
[Parameter("TDI Based Exit", DefaultValue = false)]
public bool tdiBasedExit { get; set; }
[Parameter("RR Based Exit", DefaultValue = false)]
public bool rrBasedExit { get; set; }
[Parameter("RR", DefaultValue = 2)]
public double rrAmount { get; set; }
[Parameter("Opposite Candle Exit", DefaultValue = false)]
public bool candleBasedExit { get; set; }
[Parameter("Same Exit for Profitable / Loser?", DefaultValue = false)]
public bool sameExit { get; set; }
[Parameter("Stop Trailing", DefaultValue = false)]
public bool slTrail { get; set; }
[Parameter("Pips Based?", DefaultValue = false)]
public bool pipBased { get; set; }
[Parameter("Profit", DefaultValue = 1)]
public double profitSl { get; set; }
[Parameter("Move SL", DefaultValue = 0.5)]
public double moveSl { get; set; }
[Parameter("R:R Based?", DefaultValue = false)]
public bool rrBased { get; set; }
[Parameter("Move SL to BE When Reward Reached", DefaultValue = 2)]
public double beRSl { get; set; }
[Parameter("Time Filter", DefaultValue = false)]
public bool timeFilter { get; set; }
[Parameter("Start Hour", DefaultValue = 4, MinValue = 0, MaxValue = 23)]
public int startHour { get; set; }
[Parameter("End Hour", DefaultValue = 13, MinValue = 0, MaxValue = 23)]
public int endHour { get; set; }
[Parameter("Avoid Friday?", DefaultValue = false)]
public bool avoidFriday { get; set; }
[Parameter("Order Distance", DefaultValue = 1, MinValue = 0.1, MaxValue = 20)]
public double orderDistance { get; set; }
[Parameter("% Risk Per Trade", DefaultValue = 0.5, MinValue = 0.1, MaxValue = 10.0)]
public double riskPercentage { get; set; }
[Parameter("HA Color Change Candle #", DefaultValue = 3)]
public int haColor { get; set; }
// TDI parameters
[Parameter()]
public DataSeries Source { get; set; }
[Parameter("RSI Period", DefaultValue = 13)]
public int RsiPeriod { get; set; }
[Parameter("Price Period", DefaultValue = 2)]
public int PricePeriod { get; set; }
[Parameter("Signal Period", DefaultValue = 7)]
public int SignalPeriod { get; set; }
[Parameter("Signal/Price line Distance", DefaultValue = 1)]
public double spDistance { get; set; }
[Parameter("# Previous Bars Distance Check", DefaultValue = 3)]
public int barsDistaceCheck { get; set; }
[Parameter("Volatility Band", DefaultValue = 34)]
public int Volatility { get; set; }
[Parameter("Standard Deviations", DefaultValue = 2)]
public int StDev { get; set; }
[Parameter("Price Ma Type", DefaultValue = MovingAverageType.Simple)]
public MovingAverageType PriceMaType { get; set; }
[Parameter("Signal Ma Type", DefaultValue = MovingAverageType.Simple)]
public MovingAverageType SignalMaType { get; set; }
[Parameter("Trend Filter", DefaultValue = false)]
public bool trendFilter { get; set; }
[Parameter("Over Bought/Sold Filter", DefaultValue = false)]
public bool overBSFilter { get; set; }
[Parameter("Over Bought", DefaultValue = 80)]
public double overBought { get; set; }
[Parameter("Over Sold", DefaultValue = 20)]
public double overSold { get; set; }
[Parameter("Mommentum Filter", DefaultValue = false)]
public bool mommentumFilter { get; set; }
[Parameter("Buy Mommentum", DefaultValue = 50)]
public double buyMommentum { get; set; }
[Parameter("Sell Mommentum", DefaultValue = 50)]
public double sellMommentum { get; set; }
[Parameter("Stochastic Filter", DefaultValue = true)]
public bool stochasticFilter { get; set; }
[Parameter("Stochastic Ma Type", DefaultValue = MovingAverageType.Simple)]
public MovingAverageType stMaType { get; set; }
[Parameter("%K Periods", DefaultValue = 20)]
public int kPeriods { get; set; }
[Parameter("%K Slowing", DefaultValue = 3)]
public int kSlowing { get; set; }
[Parameter("%D Periods", DefaultValue = 20)]
public int dPeriods { get; set; }
// End of TDI Parameters
private AverageTrueRange atr;
private RelativeStrengthIndex _rsi;
private MovingAverage _price;
private MovingAverage _signal;
private BollingerBands _bollingerBands;
private StochasticOscillator stochastic;
private HeikenAshi heikenAshi;
public string labelPerfix;
public string scalePerfix;
protected override void OnStart()
{
labelPerfix = "TMSBot";
scalePerfix = "scale";
if (IsBacktesting)
{
int backtestNum = new Random().Next(1, 10000);
labelPerfix += " BT " + backtestNum;
}
if (scaleIn)
{
CreateSubKey();
if (motherClose)
Positions.Closed += OnPositionClose;
}
atr = Indicators.AverageTrueRange(atrPeriod, MovingAverageType.Simple);
_rsi = Indicators.RelativeStrengthIndex(Source, RsiPeriod);
_bollingerBands = Indicators.BollingerBands(_rsi.Result, Volatility, StDev, MovingAverageType.Simple);
_price = Indicators.MovingAverage(_rsi.Result, PricePeriod, PriceMaType);
_signal = Indicators.MovingAverage(_rsi.Result, SignalPeriod, SignalMaType);
stochastic = Indicators.StochasticOscillator(kPeriods, kSlowing, dPeriods, stMaType);
heikenAshi = Indicators.GetIndicator<HeikenAshi>(1);
}
protected override void OnTick()
{
foreach (var position in Positions)
{
if (position.SymbolCode == Symbol.Code && position.Label.StartsWith(labelPerfix))
{
if (position.NetProfit > 0)
{
if (slTrail)
stopTrailing(position);
if (scaleIn)
scalingIn(position);
}
}
else if (position.SymbolCode == Symbol.Code && position.Label.StartsWith(scalePerfix))
{
if (position.NetProfit > 0)
{
if (slTrail)
stopTrailing(position);
}
}
}
}
// This method will be called after creation of each new bar instead of ticks
protected override void OnBar()
{
foreach (var order in PendingOrders)
{
if (order.Label.StartsWith(labelPerfix) && order.SymbolCode == Symbol.Code)
{
CancelPendingOrder(order);
}
}
foreach (var position in Positions)
{
if ((position.Label.StartsWith(labelPerfix) || position.Label.StartsWith(scalePerfix)) && position.SymbolCode == Symbol.Code)
{
if (position.Label.StartsWith(labelPerfix))
tradeManager(position);
return;
}
}
// Latest Closed Candle Index
int index = MarketSeries.Close.Count - 1;
bool heikenAshiOk = false;
bool bullishSignal = false;
bool bearishSignal = false;
if (heikenAshi.Close.Last(1) > heikenAshi.Open.Last(1))
{
for (int i = 2; i <= haColor + 1; i++)
if (heikenAshi.Close.Last(i) < heikenAshi.Open.Last(i))
{
heikenAshiOk = true;
bullishSignal = true;
}
}
else if (heikenAshi.Close.Last(1) < heikenAshi.Open.Last(1))
{
for (int i = 2; i <= haColor + 1; i++)
if (heikenAshi.Close.Last(i) > heikenAshi.Open.Last(i))
{
heikenAshiOk = true;
bearishSignal = true;
}
}
// TDI Check
bool tdiOk = false;
bool spDistanceCheck = false;
if ((_price.Result.Last(1) > _signal.Result.Last(1)) && (_price.Result.Last(2) < _signal.Result.Last(2)))
{
tdiOk = true;
for (int i = 2; i <= barsDistaceCheck + 1; i++)
{
if (_signal.Result.Last(i) - _price.Result.Last(i) >= spDistance)
{
spDistanceCheck = true;
}
else
{
spDistanceCheck = false;
break;
}
}
}
else if ((_price.Result.Last(1) < _signal.Result.Last(1)) && (_price.Result.Last(2) > _signal.Result.Last(2)))
{
tdiOk = true;
for (int i = 2; i <= barsDistaceCheck + 1; i++)
{
if (_price.Result.Last(i) - _signal.Result.Last(i) >= spDistance)
{
spDistanceCheck = true;
}
else
{
spDistanceCheck = false;
break;
}
}
}
// Trend Check
bool trendOk = false;
if (trendFilter)
{
if (bullishSignal && _price.Result.LastValue > _bollingerBands.Main.LastValue && _signal.Result.LastValue > _bollingerBands.Main.LastValue)
trendOk = true;
else if (bearishSignal && _price.Result.LastValue < _bollingerBands.Main.LastValue && _signal.Result.LastValue < _bollingerBands.Main.LastValue)
trendOk = true;
}
else
trendOk = true;
// Over Bought and Over Sold Filter
bool overBSOk = false;
if (overBSFilter)
{
if (bullishSignal && _price.Result.Last(1) < overBought && _signal.Result.Last(1) < overBought)
overBSOk = true;
else if (bearishSignal && _price.Result.Last(1) > overSold && _signal.Result.Last(1) > overSold)
overBSOk = true;
}
else
overBSOk = true;
// Mommentum Filter
bool mommentumFilterOk = false;
if (mommentumFilter)
{
if (bullishSignal && _price.Result.Last(1) > buyMommentum && _signal.Result.Last(1) > buyMommentum)
mommentumFilterOk = true;
else if (bearishSignal && _price.Result.Last(1) < sellMommentum && _signal.Result.Last(1) < sellMommentum)
mommentumFilterOk = true;
}
else
mommentumFilterOk = true;
// Stochastic Filter
bool stochasticOk = false;
if (tdiOk && stochasticFilter)
{
if (bullishSignal && stochastic.PercentK.Last(0) > stochastic.PercentD.Last(0))
stochasticOk = true;
else if (bearishSignal && stochastic.PercentK.Last(0) < stochastic.PercentD.Last(0))
stochasticOk = true;
}
else
stochasticOk = true;
// Time Filter
bool isTimeCorrect = false;
if (timeFilter || avoidFriday)
isTimeCorrect = timeFilterCheck();
else
isTimeCorrect = true;
// Placing The stop order
if (heikenAshiOk && tdiOk && isTimeCorrect && stochasticOk && overBSOk && trendOk && mommentumFilterOk && spDistanceCheck)
{
// Order Attributes
double stopLoss;
if (atrSl)
{
stopLoss = Math.Round((atr.Result.LastValue * Math.Pow(10, Symbol.Digits - 1)) * atrMultiplier, 1);
}
else
stopLoss = (heikenAshi.High.Last(1) - heikenAshi.Low.Last(1)) * Math.Pow(10, Symbol.Digits - 1);
double? takeProfit = null;
if (rrBasedExit)
takeProfit = stopLoss * rrAmount;
if (scaleIn)
{
SetValue("TradeLabel", "");
SetValue("TradeNumber", "0");
SetValue("PipsCount", "0");
}
long posVolume = PositionVolume(stopLoss);
string label = string.Format("{0} {1}", labelPerfix, index);
if (bullishSignal)
{
PlaceStopOrder(TradeType.Buy, Symbol, posVolume, heikenAshi.High.Last(1) + (Symbol.PipSize * orderDistance), label, stopLoss, takeProfit);
}
else if (bearishSignal)
{
PlaceStopOrder(TradeType.Sell, Symbol, posVolume, heikenAshi.Low.Last(1) - (Symbol.PipSize * orderDistance), label, stopLoss, takeProfit);
}
}
}
// Manage the trade
private void tradeManager(Position pos)
{
if (pos.TradeType == TradeType.Buy)
{
if (tdiBasedExit && _price.Result.Last(1) < _signal.Result.Last(1))
{
CloseAllPositions();
}
if (candleBasedExit)
{
if (sameExit)
{
if (heikenAshi.Open.Last(1) > heikenAshi.Close.Last(1))
{
CloseAllPositions();
}
}
else
{
if (pos.NetProfit > 0 && heikenAshi.Open.Last(1) > heikenAshi.Close.Last(1))
{
CloseAllPositions();
}
}
}
}
else if (pos.TradeType == TradeType.Sell)
{
if (tdiBasedExit && _price.Result.Last(1) > _signal.Result.Last(1))
{
CloseAllPositions();
}
if (candleBasedExit)
{
if (sameExit)
{
if (heikenAshi.Open.Last(1) < heikenAshi.Close.Last(1))
{
CloseAllPositions();
}
}
else
{
if (pos.NetProfit > 0 && heikenAshi.Open.Last(1) < heikenAshi.Close.Last(1))
{
CloseAllPositions();
}
}
}
}
}
// Stop Trailing
private void stopTrailing(Position pos)
{
double sl_pip = 0.0;
if (pos.TradeType == TradeType.Buy)
{
if (pipBased)
{
if (pos.StopLoss.HasValue && pos.StopLoss.Value > pos.EntryPrice)
{
sl_pip = ((pos.StopLoss.Value - pos.EntryPrice) * Math.Pow(10, Symbol.Digits - 1)) + profitSl;
if (pos.Pips >= sl_pip)
{
ModifyPosition(pos, pos.StopLoss.Value + (moveSl * Symbol.PipSize), pos.TakeProfit);
}
}
else
{
sl_pip = profitSl;
if (pos.Pips >= sl_pip)
{
ModifyPosition(pos, pos.EntryPrice + (moveSl * Symbol.PipSize), pos.TakeProfit);
}
}
}
if (rrBased)
{
sl_pip = (pos.EntryPrice - pos.StopLoss.Value) * Math.Pow(10, Symbol.Digits - 1);
if (pos.Pips >= (sl_pip * beRSl) && pos.StopLoss.Value < pos.EntryPrice)
{
ModifyPosition(pos, pos.EntryPrice + Symbol.PipSize, pos.TakeProfit);
}
}
}
else if (pos.TradeType == TradeType.Sell)
{
if (pipBased)
{
if (pos.StopLoss.HasValue && pos.StopLoss.Value < pos.EntryPrice)
{
sl_pip = ((pos.EntryPrice - pos.StopLoss.Value) * Math.Pow(10, Symbol.Digits - 1)) + profitSl;
if (pos.Pips > sl_pip)
{
ModifyPosition(pos, pos.StopLoss.Value - (moveSl * Symbol.PipSize), pos.TakeProfit);
}
}
else
{
sl_pip = profitSl;
if (pos.Pips > sl_pip)
{
ModifyPosition(pos, pos.EntryPrice - (moveSl * Symbol.PipSize), pos.TakeProfit);
}
}
}
if (rrBased)
{
sl_pip = (pos.StopLoss.Value - pos.EntryPrice) * Math.Pow(10, Symbol.Digits - 1);
if (pos.Pips >= (sl_pip * beRSl) && pos.StopLoss.Value > pos.EntryPrice)
{
ModifyPosition(pos, pos.EntryPrice - Symbol.PipSize, pos.TakeProfit);
}
}
}
}
// Position volume calculator
private long PositionVolume(double stopLossInPips)
{
double riskPercent = riskPercentage;
if (scaleIn)
{
int TradeNumber = int.Parse(GetFromRegistry("TradeNumber", "0"));
if (scalePositionControl && TradeNumber == 1)
riskPercent = riskPercentage / 2;
else if (scalePositionControl && TradeNumber > 1)
riskPercent = riskPercentage / (TradeNumber + 1);
}
double costPerPip = (double)((int)(Symbol.PipValue * 10000000)) / 100;
double positionSizeForRisk = Math.Round((Account.Balance * riskPercent / 100) / (stopLossInPips * costPerPip), 2);
if (positionSizeForRisk < 0.01)
positionSizeForRisk = 0.01;
return Symbol.QuantityToVolume(positionSizeForRisk);
}
// Checking the opening time of candle
private bool timeFilterCheck()
{
bool timeOk = false;
if (timeFilter && MarketSeries.OpenTime.Last(1).Hour >= startHour && MarketSeries.OpenTime.Last(1).Hour <= endHour)
timeOk = true;
else if (!timeFilter)
timeOk = true;
bool fridayOk = false;
if (avoidFriday && MarketSeries.OpenTime.Last(1).DayOfWeek != DayOfWeek.Friday)
fridayOk = true;
else if (!avoidFriday)
fridayOk = true;
if (timeOk && fridayOk)
return true;
else
return false;
}
private void CloseAllPositions()
{
foreach (var position in Positions)
{
if (position.SymbolCode == Symbol.Code && (position.Label.StartsWith(labelPerfix) || position.Label.StartsWith(scalePerfix)))
{
ClosePosition(position);
}
}
}
private void scalingIn(Position position)
{
string TradeLabel;
int TradeNumber = int.Parse(GetFromRegistry("TradeNumber", "0"));
double PipsCount = double.Parse(GetFromRegistry("PipsCount", "0"));
if (GetFromRegistry("TradeLabel", "") == "")
TradeLabel = null;
else
TradeLabel = GetFromRegistry("TradeLabel", "");
if (limitScalingIn && TradeNumber >= scaleNumber)
return;
double sl;
if (atrSl)
{
sl = Math.Round((atr.Result.LastValue * Math.Pow(10, Symbol.Digits - 1)) * atrMultiplier, 1);
}
else
sl = (heikenAshi.High.Last(1) - heikenAshi.Low.Last(1)) * Math.Pow(10, Symbol.Digits - 1);
long volume;
double? tp;
if (rrBasedExit)
tp = sl * rrAmount;
else
tp = null;
// If it's then scale in
if (position.Pips >= PipsCount && TradeLabel == null)
{
TradeNumber = 1;
SetValue("TradeNumber", TradeNumber.ToString());
volume = PositionVolume(sl);
TradeLabel = string.Format("{0} {1} {2}", scalePerfix, position.Label, TradeNumber);
SetValue("TradeLabel", TradeLabel);
ExecuteMarketOrder(position.TradeType, Symbol, volume, TradeLabel, sl, tp);
PipsCount += scalePips;
SetValue("PipsCount", PipsCount.ToString());
}
else if (TradeLabel != null)
{
var pos = Positions.Find(TradeLabel);
if (pos != null && pos.Pips >= PipsCount)
{
TradeNumber += 1;
SetValue("TradeNumber", TradeNumber.ToString());
volume = PositionVolume(sl);
TradeLabel = string.Format("{0} {1} {2}", scalePerfix, position.Label, TradeNumber);
SetValue("TradeLabel", TradeLabel);
ExecuteMarketOrder(position.TradeType, Symbol, volume, TradeLabel, sl, tp);
PipsCount += scalePips;
SetValue("PipsCount", PipsCount.ToString());
}
}
}
// Setting, getting and deleting of Registry data
private void CreateSubKey()
{
RegistryKey softwarekey = Registry.CurrentUser.OpenSubKey("Software", true);
RegistryKey botKey = softwarekey.CreateSubKey(labelPerfix);
softwarekey.Close();
botKey.Close();
}
private void SetValue(string name, string v)
{
RegistryKey botKey = Registry.CurrentUser.OpenSubKey("Software\\" + labelPerfix + "\\", true);
botKey.SetValue(name, (object)v, RegistryValueKind.String);
botKey.Close();
}
private string GetFromRegistry(string valueName, string defaultValue)
{
RegistryKey botKey = Registry.CurrentUser.OpenSubKey("Software\\" + labelPerfix + "\\", false);
string valueData = (string)botKey.GetValue(valueName, (object)defaultValue);
botKey.Close();
return valueData;
}
private void DeleteRegistryValue(string name)
{
if (GetFromRegistry(name, "0") != "0")
{
RegistryKey botKey = Registry.CurrentUser.OpenSubKey("Software\\" + labelPerfix + "\\", true);
botKey.DeleteValue(name);
botKey.Close();
}
}
private void DeleteRegistryKey()
{
bool noOpenPosition = true;
if (!IsBacktesting)
{
foreach (var position in Positions)
{
if (position.SymbolCode == Symbol.Code && (position.Label.StartsWith(labelPerfix) || position.Label.StartsWith(scalePerfix)))
{
noOpenPosition = false;
break;
}
}
}
if (scaleIn && noOpenPosition)
{
RegistryKey softwarekey = Registry.CurrentUser.OpenSubKey("Software", true);
softwarekey.DeleteSubKey(labelPerfix);
softwarekey.Close();
}
}
private void OnPositionClose(PositionClosedEventArgs args)
{
var position = args.Position;
DeleteRegistryValue(position.Label);
if (scaleIn && motherClose && position.Pips < 0 && position.Label.StartsWith(labelPerfix))
{
foreach (var pos in Positions)
{
if (pos.Label.Contains(position.Label))
ClosePosition(pos);
}
}
}
protected override void OnStop()
{
DeleteRegistryKey();
}
}
}
Harold_182236
07 Nov 2016, 11:26
RE: Error CS1061 Follow up queries! Help, anyone.
Harold_182236 said:
I did some work on the Indicator (Heiken Ashi), and the Robot compiled successfully. However, I am still having a bit of issues. The Robot is not taking any trade whwn I did a backtest.
Can anyone help with how I may correct this problem. Please take a look at the codes for the Robot, and the Indicator, below:
1. Heiken Ashi cBot
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
namespace cAlgo
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class HeikinAshiBot : Robot
{
[Parameter("Label Perfix", DefaultValue = "HeikinAshiBot")]
public string labelPerfix { get; set; }
[Parameter("Multiple Trades?", DefaultValue = false)]
public bool multipleTrades { get; set; }
[Parameter("Check Previous Candles", DefaultValue = true)]
public bool checkPreviousCandles { get; set; }
[Parameter("Previous Opposite Candles", DefaultValue = 1, MinValue = 1, MaxValue = 10)]
public int previousOppositeCandles { get; set; }
[Parameter("ATR Based SL", DefaultValue = false)]
public bool atrSl { get; set; }
[Parameter("ATR Periods", DefaultValue = 20)]
public int atrPeriod { get; set; }
[Parameter("ATR Multiplier", DefaultValue = 3)]
public int atrMultiplier { get; set; }
[Parameter("ADX Filter", DefaultValue = false)]
public bool adxFilter { get; set; }
[Parameter("ADX Periods", DefaultValue = 14)]
public int adxPeriods { get; set; }
[Parameter("ADX Trend", DefaultValue = 25)]
public int adxTrend { get; set; }
[Parameter("Volatility Filter", DefaultValue = false)]
public bool volatilityFilter { get; set; }
[Parameter("Chaikin Periods", DefaultValue = 14)]
public int chaikinPeriods { get; set; }
[Parameter("Chaikin Rate Of Change", DefaultValue = 10)]
public int chaikinRate { get; set; }
[Parameter("Chaikin MA Type", DefaultValue = MovingAverageType.Simple)]
public MovingAverageType chaikinMaType { get; set; }
[Parameter("Chaikin Value", DefaultValue = 0)]
public int chaikinValue { get; set; }
[Parameter("MACD Histogram Filter", DefaultValue = false)]
public bool macdFilter { get; set; }
[Parameter("Long Cycle", DefaultValue = 26)]
public int longCycle { get; set; }
[Parameter("Short Cycle", DefaultValue = 12)]
public int shortCycle { get; set; }
[Parameter("Signal Periods", DefaultValue = 9)]
public int signalPeriods { get; set; }
[Parameter("MA Trend Filter", DefaultValue = false)]
public bool maFilter { get; set; }
[Parameter("MA Type", DefaultValue = MovingAverageType.Simple)]
public MovingAverageType MAType { get; set; }
[Parameter("Source")]
public DataSeries SourceSeries { get; set; }
[Parameter("Slow Periods", DefaultValue = 20)]
public int SlowPeriods { get; set; }
[Parameter("Fast Periods", DefaultValue = 10)]
public int FastPeriods { get; set; }
[Parameter("MAs Distance(pip)", DefaultValue = 1)]
public int maDistance { get; set; }
[Parameter("MA Based Exit", DefaultValue = false)]
public bool maBasedExit { get; set; }
[Parameter("MACD Histogram Based Exit", DefaultValue = false)]
public bool macdBasedExit { get; set; }
[Parameter("Reward Based Exit", DefaultValue = false)]
public bool rrBasedExit { get; set; }
[Parameter("Number of Reward", DefaultValue = 2)]
public double rrAmount { get; set; }
[Parameter("Exit on Opposite Candle?", DefaultValue = false)]
public bool exitOppositeCandle { get; set; }
[Parameter("Same Exit for Profitable / Loser?", DefaultValue = false)]
public bool sameExit { get; set; }
[Parameter("Stop Trailing", DefaultValue = false)]
public bool slTrail { get; set; }
[Parameter("Chandelier SL Trailing", DefaultValue = false)]
public bool chandelierSlTrail { get; set; }
[Parameter("Chandelier Multiplier(pips)", DefaultValue = 0.5)]
public double chandelierMultiplier { get; set; }
[Parameter("Trail to Break Even", DefaultValue = false)]
public bool bTrail { get; set; }
[Parameter("Decrease SL 50% When Reward Reached", DefaultValue = 1.5)]
public double fiftySl { get; set; }
[Parameter("Move SL to BE When Reward Reached", DefaultValue = 2)]
public double beRSl { get; set; }
[Parameter("RR Based SL Trailing", DefaultValue = false)]
public bool rrSlTrail { get; set; }
[Parameter("When Reward Reached", DefaultValue = 2)]
public double rrMultiplier { get; set; }
[Parameter("Move SL to(Reward)", DefaultValue = 1)]
public double moveSlR { get; set; }
[Parameter("Time Filter", DefaultValue = false)]
public bool timeFilter { get; set; }
[Parameter("Start Hour", DefaultValue = 7, MinValue = 0, MaxValue = 23)]
public int startHour { get; set; }
[Parameter("End Hour", DefaultValue = 13, MinValue = 0, MaxValue = 23)]
public int endHour { get; set; }
[Parameter("Avoid Monday?", DefaultValue = false)]
public bool avoidMonday { get; set; }
[Parameter("Avoid Friday?", DefaultValue = false)]
public bool avoidFriday { get; set; }
[Parameter("Avoid December?", DefaultValue = false)]
public bool avoidDecember { get; set; }
[Parameter("Order Distance", DefaultValue = 1, MinValue = 0.1, MaxValue = 10)]
public double orderDistance { get; set; }
[Parameter("% Risk Per Trade", DefaultValue = 1, MinValue = 0.1, MaxValue = 10.0)]
public double riskPercentage { get; set; }
public double stopLoss = 0.0;
public double? takeProfit = 0.0;
public bool breakEven = false;
public double chandelierProfit = 0.0;
public string label = null;
private MovingAverage slowMa;
private MovingAverage fastMa;
private AverageTrueRange atr;
private HeikenAshi _heikenAshi;
private ChaikinVolatility _chaikin;
private MacdHistogram _macdHistogram;
private DirectionalMovementSystem adx;
protected override void OnStart()
{
_heikenAshi = Indicators.GetIndicator<HeikenAshi>(1);
_macdHistogram = Indicators.MacdHistogram(longCycle, shortCycle, signalPeriods);
fastMa = Indicators.MovingAverage(SourceSeries, FastPeriods, MAType);
slowMa = Indicators.MovingAverage(SourceSeries, SlowPeriods, MAType);
atr = Indicators.AverageTrueRange(atrPeriod, MAType);
_chaikin = Indicators.ChaikinVolatility(chaikinPeriods, chaikinRate, chaikinMaType);
adx = Indicators.DirectionalMovementSystem(adxPeriods);
}
protected override void OnTick()
{
foreach (var position in Positions)
{
if (position.Label.StartsWith(labelPerfix) && position.NetProfit > 0 && slTrail)
{
stopTrailing(position);
}
}
}
protected override void OnBar()
{
foreach (var order in PendingOrders)
{
if (order.Label == label && order.SymbolCode == Symbol.Code)
{
CancelPendingOrder(order);
}
}
// If the order was executed then it will throw it to tradeManager method
foreach (var position in Positions)
{
if (position.Label.StartsWith(labelPerfix))
{
tradeManager(position);
if (!multipleTrades)
return;
}
}
// Type check
bool bullishHa = false;
bool bearishHa = false;
if (_heikenAshi.Open.Last(1) < _heikenAshi.Close.Last(1))
{
bullishHa = true;
}
else if (_heikenAshi.Open.Last(1) > _heikenAshi.Close.Last(1))
{
bearishHa = true;
}
// Time Filter
bool isTimeCorrect = false;
if (timeFilter || avoidDecember || avoidFriday || avoidMonday)
isTimeCorrect = timeFilterCheck();
else
isTimeCorrect = true;
// ADX
bool adxOk = false;
if (adxFilter)
{
if (adx.ADX.LastValue > adxTrend)
adxOk = true;
}
else
adxOk = true;
// MACD Histogram
bool macdHistogramOk = false;
if (macdFilter)
{
if (bullishHa && _macdHistogram.Histogram.Last(1) > 0)
macdHistogramOk = true;
else if (bearishHa && _macdHistogram.Histogram.Last(1) < 0)
macdHistogramOk = true;
}
else
macdHistogramOk = true;
// Previous Candle Check
bool previousCandleCheck = false;
if (checkPreviousCandles)
{
if (bullishHa)
{
for (int i = 2; i <= previousOppositeCandles + 1; i++)
{
if (_heikenAshi.Close.Last(i) < _heikenAshi.Open.Last(i))
{
previousCandleCheck = true;
}
else
{
previousCandleCheck = false;
break;
}
}
}
if (bearishHa)
{
for (int i = 2; i <= previousOppositeCandles + 1; i++)
{
if (_heikenAshi.Close.Last(i) > _heikenAshi.Open.Last(i))
{
previousCandleCheck = true;
}
else
{
previousCandleCheck = false;
break;
}
}
}
}
else
previousCandleCheck = true;
// MA Filter
bool isMaOk = false;
if (maFilter)
{
bool mDistance = false;
if (bullishHa && fastMa.Result.Last(0) > slowMa.Result.Last(0) && _heikenAshi.Low.Last(1) < fastMa.Result.Last(0))
{
mDistance = (fastMa.Result.Last(0) - slowMa.Result.Last(0)) * Math.Pow(10, Symbol.Digits - 1) >= maDistance;
if (mDistance)
isMaOk = true;
}
else if (bearishHa && fastMa.Result.Last(0) < slowMa.Result.Last(0) && _heikenAshi.High.Last(1) > fastMa.Result.Last(0))
{
mDistance = (slowMa.Result.Last(0) - fastMa.Result.Last(0)) * Math.Pow(10, Symbol.Digits - 1) >= maDistance;
if (mDistance)
isMaOk = true;
}
else
isMaOk = false;
}
else
isMaOk = true;
// Volatility Filter
bool volatilityOk = false;
if (volatilityFilter)
{
if (_chaikin.Result.LastValue > 0 && _chaikin.Result.Last(1) > _chaikin.Result.Last(2))
volatilityOk = true;
}
else
volatilityOk = true;
// Placing The stop order
if (isTimeCorrect && isMaOk && previousCandleCheck && volatilityOk && adxOk && macdHistogramOk)
{
// Order Attributes
if (atrSl)
{
stopLoss = Math.Round((atr.Result.LastValue * Math.Pow(10, Symbol.Digits - 1)) * atrMultiplier, 1);
}
else
stopLoss = (_heikenAshi.High.Last(1) - _heikenAshi.Low.Last(1)) * Math.Pow(10, Symbol.Digits - 1);
if (rrBasedExit)
takeProfit = stopLoss * rrAmount;
long posVolume = PositionVolume(stopLoss);
breakEven = false;
label = string.Format("{0} {1}", labelPerfix, _heikenAshi.Close.Count - 1);
chandelierProfit = 0.0;
if (bullishHa)
{
if (takeProfit.Value != 0.0)
{
PlaceStopOrder(TradeType.Buy, Symbol, posVolume, _heikenAshi.High.Last(1) + (Symbol.PipSize * orderDistance), label, stopLoss, takeProfit.Value);
takeProfit = 0.0;
}
else
PlaceStopOrder(TradeType.Buy, Symbol, posVolume, _heikenAshi.High.Last(1) + (Symbol.PipSize * orderDistance), label, stopLoss, null);
}
else if (bearishHa)
{
if (takeProfit.Value != 0.0)
{
PlaceStopOrder(TradeType.Sell, Symbol, posVolume, _heikenAshi.Low.Last(1) - (Symbol.PipSize * orderDistance), label, stopLoss, takeProfit.Value);
takeProfit = 0.0;
}
else
PlaceStopOrder(TradeType.Sell, Symbol, posVolume, _heikenAshi.Low.Last(1) - (Symbol.PipSize * orderDistance), label, stopLoss, null);
}
}
}
// Manage the trade
private void tradeManager(Position position)
{
if (position.TradeType == TradeType.Buy)
{
if (maBasedExit)
{
if (fastMa.Result.LastValue < slowMa.Result.LastValue)
ClosePosition(position);
}
if (macdBasedExit)
{
if (_macdHistogram.Histogram.Last(1) < 0)
ClosePosition(position);
}
if (exitOppositeCandle)
{
if (sameExit)
{
if (_heikenAshi.Open.Last(1) > _heikenAshi.Close.Last(1))
ClosePosition(position);
}
else
{
if (position.NetProfit > 0 && _heikenAshi.Open.Last(1) > _heikenAshi.Close.Last(1))
ClosePosition(position);
}
}
}
else if (position.TradeType == TradeType.Sell)
{
if (maBasedExit)
{
if (fastMa.Result.LastValue > slowMa.Result.LastValue)
ClosePosition(position);
}
if (macdBasedExit)
{
if (_macdHistogram.Histogram.Last(1) > 0)
ClosePosition(position);
}
if (exitOppositeCandle)
{
if (sameExit)
{
if (_heikenAshi.Open.Last(1) < _heikenAshi.Close.Last(1))
ClosePosition(position);
}
else
{
if (position.NetProfit > 0 && _heikenAshi.Open.Last(1) < _heikenAshi.Close.Last(1))
ClosePosition(position);
}
}
}
}
// It will trail SL to break even
private void stopTrailing(Position pos)
{
double sl_pip = 0.0;
if (pos.TradeType == TradeType.Buy)
{
sl_pip = (pos.EntryPrice - pos.StopLoss.Value) * Math.Pow(10, Symbol.Digits - 1);
// Chandelier Exit
if (chandelierSlTrail)
{
bTrail = false;
rrSlTrail = false;
if (pos.Pips > chandelierProfit && (pos.Pips - chandelierProfit) >= chandelierMultiplier)
{
chandelierProfit = pos.Pips;
ModifyPosition(pos, pos.StopLoss + (chandelierMultiplier * Symbol.PipSize), pos.TakeProfit);
}
}
// Decrease 50% of SL
if (bTrail && pos.Pips >= (sl_pip * fiftySl) && pos.StopLoss.Value < pos.EntryPrice && sl_pip >= stopLoss)
ModifyPosition(pos, ((sl_pip / 2) * Symbol.PipSize) + pos.StopLoss, pos.TakeProfit);
// Move SL to break even
if (bTrail && pos.Pips >= (sl_pip * beRSl) && pos.StopLoss.Value < pos.EntryPrice && !breakEven)
{
ModifyPosition(pos, pos.EntryPrice + Symbol.PipSize, pos.TakeProfit);
breakEven = true;
}
// Move SL to spcified number of R when price reached spcified R
if (rrSlTrail && ((Symbol.Ask - pos.StopLoss.Value) * Math.Pow(10, Symbol.Digits - 1)) == (stopLoss * rrMultiplier))
{
ModifyPosition(pos, pos.StopLoss.Value + (stopLoss * moveSlR * Symbol.PipSize), pos.TakeProfit);
}
}
else if (pos.TradeType == TradeType.Sell)
{
sl_pip = (pos.StopLoss.Value - pos.EntryPrice) * Math.Pow(10, Symbol.Digits - 1);
if (chandelierSlTrail)
{
bTrail = false;
rrSlTrail = false;
if (pos.Pips > chandelierProfit && (pos.Pips - chandelierProfit) >= chandelierMultiplier)
{
chandelierProfit = pos.Pips;
ModifyPosition(pos, pos.StopLoss - (chandelierMultiplier * Symbol.PipSize), pos.TakeProfit);
}
}
if (bTrail && pos.Pips >= (sl_pip * fiftySl) && pos.StopLoss.Value > pos.EntryPrice && sl_pip >= stopLoss)
ModifyPosition(pos, pos.StopLoss - ((sl_pip / 2) * Symbol.PipSize), pos.TakeProfit);
if (bTrail && pos.Pips >= (sl_pip * beRSl) && pos.StopLoss.Value > pos.EntryPrice && !breakEven)
{
ModifyPosition(pos, pos.EntryPrice - Symbol.PipSize, pos.TakeProfit);
breakEven = true;
}
if (rrSlTrail && ((pos.StopLoss.Value - Symbol.Bid) * Math.Pow(10, Symbol.Digits - 1)) == (stopLoss * rrMultiplier))
{
ModifyPosition(pos, pos.StopLoss.Value - (stopLoss * moveSlR * Symbol.PipSize), pos.TakeProfit);
}
}
}
// Position volume calculator
private long PositionVolume(double stopLossInPips)
{
double costPerPip = (double)((int)(Symbol.PipValue * 10000000)) / 100;
double positionSizeForRisk = Math.Round((Account.Balance * riskPercentage / 100) / (stopLossInPips * costPerPip), 2);
if (positionSizeForRisk < 0.01)
positionSizeForRisk = 0.01;
return Symbol.QuantityToVolume(positionSizeForRisk);
}
// Checking the opening time of candle
private bool timeFilterCheck()
{
bool timeOk = false;
if (timeFilter && MarketSeries.OpenTime.Last(1).Hour >= startHour && MarketSeries.OpenTime.Last(1).Hour <= endHour)
timeOk = true;
else if (!timeFilter)
timeOk = true;
bool decemberOk = false;
if (avoidDecember && MarketSeries.OpenTime.Last(1).Month != 12)
decemberOk = true;
else if (!avoidDecember)
decemberOk = true;
bool mondayOk = false;
if (avoidMonday && MarketSeries.OpenTime.Last(1).DayOfWeek != DayOfWeek.Monday)
mondayOk = true;
else if (!avoidMonday)
mondayOk = true;
bool fridayOk = false;
if (avoidFriday && MarketSeries.OpenTime.Last(1).DayOfWeek != DayOfWeek.Friday)
fridayOk = true;
else if (!avoidFriday)
fridayOk = true;
if (timeOk && decemberOk && mondayOk && fridayOk)
return true;
else
return false;
}
}
}
2. Heiken Ashi Indicator
using System;
using cAlgo.API;
using cAlgo.API.Indicators;
namespace cAlgo.Indicators
{
[Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
public class HeikenAshi : Indicator
{
private IndicatorDataSeries _haOpen;
private IndicatorDataSeries _haClose;
[Parameter("Candle width", DefaultValue = 5)]
public int CandleWidth { get; set; }
[Parameter("Up color", DefaultValue = "Blue")]
public string UpColor { get; set; }
[Parameter("Down color", DefaultValue = "Red")]
public string DownColor { get; set; }
public DataSeries Open
{
get { return MarketSeries.Open; }
}
public DataSeries Close
{
get { return MarketSeries.Close; }
}
public DataSeries High
{
get { return MarketSeries.High; }
}
public DataSeries Low
{
get { return MarketSeries.Low; }
}
private Colors _upColor;
private Colors _downColor;
private bool _incorrectColors;
private Random _random = new Random();
protected override void Initialize()
{
_haOpen = CreateDataSeries();
_haClose = CreateDataSeries();
if (!Enum.TryParse<Colors>(UpColor, out _upColor) || !Enum.TryParse<Colors>(DownColor, out _downColor))
_incorrectColors = true;
}
public override void Calculate(int index)
{
if (_incorrectColors)
{
var errorColor = _random.Next(2) == 0 ? Colors.Red : Colors.White;
ChartObjects.DrawText("Error", "Incorrect colors", StaticPosition.Center, errorColor);
return;
}
this.CalculateHeikenAshiValues(index);
}
private void CalculateHeikenAshiValues(int index)
{
var haClose = this.CalculateCloseAverageAtIndex(index);
var haOpen = this.CalculateOpenAverateAtIndex(index);
var haHigh = Math.Max(Math.Max(this.High[index], haOpen), haClose);
var haLow = Math.Min(Math.Min(this.Low[index], haOpen), haClose);
var color = haOpen > haClose ? _downColor : _upColor;
ChartObjects.DrawLine("candle" + index, index, haOpen, index, haClose, color, CandleWidth, LineStyle.Solid);
ChartObjects.DrawLine("line" + index, index, haHigh, index, haLow, color, 1, LineStyle.Solid);
this._haOpen[index] = haOpen;
this._haClose[index] = haClose;
}
private double CalculateCloseAverageAtIndex(int index)
{
return (this.Open[index] + this.High[index] + this.Low[index] + this.Close[index]) / 4;
}
private double CalculateOpenAverateAtIndex(int index)
{
if (index == 0)
return (this.Open[index] + this.Close[index]) / 2;
return (this._haOpen[index - 1] + this._haClose[index - 1]) / 2;
}
}
}
Thanks,
@Harold_182236