Multi-timeframe trading and one buy/one sell per period
Multi-timeframe trading and one buy/one sell per period
09 Mar 2022, 13:15
Hi, I am building a basic EA to test multi-timeframe trading, and I am having some trouble in that bot does not create any trades.
The bot needs to buy when Bull Price > Previous Period High (Bull Price = Price + Safety in Pips)
And sell when Bear Price < Previous Period Low open sell (Bear Price = Price - Safety in Pips)
Additionally, one of each (buy or sell) is allowed per trading day.
Here I have attached the code I am having problems with:
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
public class AFFS : Robot
{
[Parameter("Name", DefaultValue = "AFFS")]
public string _name { get; set; }
[Parameter("Start Hour", DefaultValue = 6.0)]
public double _starttime { get; set; }
[Parameter("Stop Hour", DefaultValue = 18.0)]
public double _stoptime { get; set; }
[Parameter("Max Lots", DefaultValue = 100.0, MinValue = 0.01, MaxValue = 1000.0)]
public double _maxlots { get; set; }
[Parameter("Starting Risk (%)", DefaultValue = 1.0, MinValue = 0.01, MaxValue = 100.0)]
public double _startingrisk { get; set; }
[Parameter("Risk Step (%)", DefaultValue = 1.0, MinValue = 0.01, MaxValue = 100.0)]
public double _riskstep { get; set; }
[Parameter("Take Profit", DefaultValue = 5.0, MinValue = 0.1, MaxValue = 100.0)]
public double _takeprofit { get; set; }
[Parameter("Stop Loss", DefaultValue = 10.0, MinValue = 0.1, MaxValue = 100.0)]
public double _stoploss { get; set; }
[Parameter("Safety (Pips)", DefaultValue = 3.0, MinValue = 0.1, MaxValue = 100.0)]
public double _safety { get; set; }
[Parameter("High/Low Timeframe", DefaultValue = "Daily")]
public TimeFrame _hltf { get; set; }
private Bars _hlbars;
private double _bullprice, _bearprice, _previoushigh, _previouslow, _maxunits, _activerisk;
private bool _todaybuy, _todaysell;
protected override void OnStart()
{
_hlbars = MarketData.GetBars(_hltf);
}
protected override void OnBar()
{
var _currenthours = Server.Time.TimeOfDay.TotalHours;
bool _tradetime = _starttime < _stoptime ? _currenthours > _starttime && _currenthours < _stoptime : _currenthours < _stoptime || _currenthours > _starttime;
_activerisk = GetRisk();
var _volume = GetVolume();
_maxunits = Symbol.QuantityToVolumeInUnits(_maxlots);
if (_volume > _maxunits)
{
_volume = _maxunits;
}
_previoushigh = _hlbars.HighPrices.Last(1);
_previouslow = _hlbars.LowPrices.Last(1);
_bullprice = Symbol.Ask + (_safety / Symbol.PipValue);
_bearprice = Symbol.Bid - (_safety / Symbol.PipValue);
if (_tradetime && !_todaybuy)
{
if (_bullprice > _previoushigh)
{
ExecuteMarketOrder(TradeType.Buy, Symbol.Name, _volume, _name, _stoploss, _takeprofit);
_todaybuy = true;
}
}
if (!_tradetime && _todaybuy)
{
_todaybuy = false;
}
if (_tradetime && !_todaysell)
{
if (_bearprice < _previouslow)
{
ExecuteMarketOrder(TradeType.Sell, Symbol.Name, _volume, _name, _stoploss, _takeprofit);
_todaysell = true;
}
}
if (!_tradetime && _todaysell)
{
_todaysell = false;
}
}
private double GetRisk()
{
double _result = 0.0;
double _maxrisk = 10.0;
var _lastposition = History.FindLast(_name);
bool _win = _lastposition.NetProfit > 0.0 ? true : false;
if (_win && _activerisk < _maxrisk)
{
_result = _activerisk + _riskstep;
}
else if (!_win)
{
_result = _startingrisk;
}
return _result;
}
private double GetVolume()
{
double costPerPip = (double)((int)(Symbol.PipValue * 10000000)) / 100;
double baseNumber = Account.Balance;
double sizeInLots = Math.Round((baseNumber * _activerisk / 100) / (_stoploss * costPerPip), 2);
var result = Symbol.QuantityToVolumeInUnits(sizeInLots);
if (result > Symbol.VolumeInUnitsMax)
{
result = Symbol.VolumeInUnitsMax;
}
else if (result < Symbol.VolumeInUnitsMin)
{
result = Symbol.VolumeInUnitsMin;
}
else if (result % Symbol.VolumeInUnitsStep != 0)
{
result = result - (result % Symbol.VolumeInUnitsStep);
}
return result;
}
}
}
Replies
wmclennan77
10 Mar 2022, 13:25
RE:
amusleh said:
Hi,
Try this:
using System; using System.Linq; using cAlgo.API; using cAlgo.API.Indicators; using cAlgo.API.Internals; using cAlgo.Indicators; namespace cAlgo.Robots { [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)] public class AFFS : Robot { [Parameter("Name", DefaultValue = "AFFS")] public string _name { get; set; } [Parameter("Start Hour", DefaultValue = 6.0)] public double _starttime { get; set; } [Parameter("Stop Hour", DefaultValue = 18.0)] public double _stoptime { get; set; } [Parameter("Max Lots", DefaultValue = 100.0, MinValue = 0.01, MaxValue = 1000.0)] public double _maxlots { get; set; } [Parameter("Starting Risk (%)", DefaultValue = 1.0, MinValue = 0.01, MaxValue = 100.0)] public double _startingrisk { get; set; } [Parameter("Risk Step (%)", DefaultValue = 1.0, MinValue = 0.01, MaxValue = 100.0)] public double _riskstep { get; set; } [Parameter("Take Profit", DefaultValue = 5.0, MinValue = 0.1, MaxValue = 100.0)] public double _takeprofit { get; set; } [Parameter("Stop Loss", DefaultValue = 10.0, MinValue = 0.1, MaxValue = 100.0)] public double _stoploss { get; set; } [Parameter("Safety (Pips)", DefaultValue = 3.0, MinValue = 0.1, MaxValue = 100.0)] public double _safety { get; set; } [Parameter("High/Low Timeframe", DefaultValue = "Daily")] public TimeFrame _hltf { get; set; } private Bars _hlbars; private double _bullprice, _bearprice, _previoushigh, _previouslow, _maxunits, _activerisk; private bool _todaybuy, _todaysell; protected override void OnStart() { _hlbars = MarketData.GetBars(_hltf); _safety *= Symbol.PipSize; } protected override void OnBar() { var _currenthours = Server.Time.TimeOfDay.TotalHours; bool _tradetime = _starttime < _stoptime ? _currenthours > _starttime && _currenthours < _stoptime : _currenthours < _stoptime || _currenthours > _starttime; _activerisk = GetRisk(); var _volume = GetVolume(); _maxunits = Symbol.QuantityToVolumeInUnits(_maxlots); if (_volume > _maxunits) { _volume = _maxunits; } _previoushigh = _hlbars.HighPrices.Last(1); _previouslow = _hlbars.LowPrices.Last(1); _bullprice = Symbol.Ask + _safety; _bearprice = Symbol.Bid - _safety; if (_tradetime && !_todaybuy) { if (_bullprice > _previoushigh) { ExecuteMarketOrder(TradeType.Buy, Symbol.Name, _volume, _name, _stoploss, _takeprofit); _todaybuy = true; } } if (!_tradetime && _todaybuy) { _todaybuy = false; } if (_tradetime && !_todaysell) { if (_bearprice < _previouslow) { ExecuteMarketOrder(TradeType.Sell, Symbol.Name, _volume, _name, _stoploss, _takeprofit); _todaysell = true; } } if (!_tradetime && _todaysell) { _todaysell = false; } } private double GetRisk() { double _result = 0.0; double _maxrisk = 10.0; var _lastposition = History.FindLast(_name); bool _win = _lastposition != null && _lastposition.NetProfit > 0.0 ? true : false; if (_win && _activerisk < _maxrisk) { _result = _activerisk + _riskstep; } else if (!_win) { _result = _startingrisk; } return _result; } private double GetVolume() { double costPerPip = (double)((int)(Symbol.PipValue * 10000000)) / 100; double baseNumber = Account.Balance; double sizeInLots = Math.Round((baseNumber * _activerisk / 100) / (_stoploss * costPerPip), 2); var result = Symbol.QuantityToVolumeInUnits(sizeInLots); if (result > Symbol.VolumeInUnitsMax) { result = Symbol.VolumeInUnitsMax; } else if (result < Symbol.VolumeInUnitsMin) { result = Symbol.VolumeInUnitsMin; } else if (result % Symbol.VolumeInUnitsStep != 0) { result = result - (result % Symbol.VolumeInUnitsStep); } return result; } } }
Hi amusleh,
Thanks, works perfectly!
@wmclennan77
wmclennan77
11 Mar 2022, 11:42
RE:
amusleh said:
Hi,
Try this:
using System; using System.Linq; using cAlgo.API; using cAlgo.API.Indicators; using cAlgo.API.Internals; using cAlgo.Indicators; namespace cAlgo.Robots { [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)] public class AFFS : Robot { [Parameter("Name", DefaultValue = "AFFS")] public string _name { get; set; } [Parameter("Start Hour", DefaultValue = 6.0)] public double _starttime { get; set; } [Parameter("Stop Hour", DefaultValue = 18.0)] public double _stoptime { get; set; } [Parameter("Max Lots", DefaultValue = 100.0, MinValue = 0.01, MaxValue = 1000.0)] public double _maxlots { get; set; } [Parameter("Starting Risk (%)", DefaultValue = 1.0, MinValue = 0.01, MaxValue = 100.0)] public double _startingrisk { get; set; } [Parameter("Risk Step (%)", DefaultValue = 1.0, MinValue = 0.01, MaxValue = 100.0)] public double _riskstep { get; set; } [Parameter("Take Profit", DefaultValue = 5.0, MinValue = 0.1, MaxValue = 100.0)] public double _takeprofit { get; set; } [Parameter("Stop Loss", DefaultValue = 10.0, MinValue = 0.1, MaxValue = 100.0)] public double _stoploss { get; set; } [Parameter("Safety (Pips)", DefaultValue = 3.0, MinValue = 0.1, MaxValue = 100.0)] public double _safety { get; set; } [Parameter("High/Low Timeframe", DefaultValue = "Daily")] public TimeFrame _hltf { get; set; } private Bars _hlbars; private double _bullprice, _bearprice, _previoushigh, _previouslow, _maxunits, _activerisk; private bool _todaybuy, _todaysell; protected override void OnStart() { _hlbars = MarketData.GetBars(_hltf); _safety *= Symbol.PipSize; } protected override void OnBar() { var _currenthours = Server.Time.TimeOfDay.TotalHours; bool _tradetime = _starttime < _stoptime ? _currenthours > _starttime && _currenthours < _stoptime : _currenthours < _stoptime || _currenthours > _starttime; _activerisk = GetRisk(); var _volume = GetVolume(); _maxunits = Symbol.QuantityToVolumeInUnits(_maxlots); if (_volume > _maxunits) { _volume = _maxunits; } _previoushigh = _hlbars.HighPrices.Last(1); _previouslow = _hlbars.LowPrices.Last(1); _bullprice = Symbol.Ask + _safety; _bearprice = Symbol.Bid - _safety; if (_tradetime && !_todaybuy) { if (_bullprice > _previoushigh) { ExecuteMarketOrder(TradeType.Buy, Symbol.Name, _volume, _name, _stoploss, _takeprofit); _todaybuy = true; } } if (!_tradetime && _todaybuy) { _todaybuy = false; } if (_tradetime && !_todaysell) { if (_bearprice < _previouslow) { ExecuteMarketOrder(TradeType.Sell, Symbol.Name, _volume, _name, _stoploss, _takeprofit); _todaysell = true; } } if (!_tradetime && _todaysell) { _todaysell = false; } } private double GetRisk() { double _result = 0.0; double _maxrisk = 10.0; var _lastposition = History.FindLast(_name); bool _win = _lastposition != null && _lastposition.NetProfit > 0.0 ? true : false; if (_win && _activerisk < _maxrisk) { _result = _activerisk + _riskstep; } else if (!_win) { _result = _startingrisk; } return _result; } private double GetVolume() { double costPerPip = (double)((int)(Symbol.PipValue * 10000000)) / 100; double baseNumber = Account.Balance; double sizeInLots = Math.Round((baseNumber * _activerisk / 100) / (_stoploss * costPerPip), 2); var result = Symbol.QuantityToVolumeInUnits(sizeInLots); if (result > Symbol.VolumeInUnitsMax) { result = Symbol.VolumeInUnitsMax; } else if (result < Symbol.VolumeInUnitsMin) { result = Symbol.VolumeInUnitsMin; } else if (result % Symbol.VolumeInUnitsStep != 0) { result = result - (result % Symbol.VolumeInUnitsStep); } return result; } } }
Hi amusleh,
I have one more issue if you can help me.
In the bot above, is there any way to check in the OnStart if:
In the _hlbars period, the one entry for the day has already happened? If so, the bot cannot trade until the next period.
For example, if HL is set to daily and I start the bot at 2 PM and today's entry happened at 1 PM, I don't want the bot to trade until the next day.
What is happening now is when I initialize the bot, the logic sees that the current price is higher than the previous high, and makes a buy immediately. This is wrong since the ideal entry has passed.
Any help would be greatly appreciated, thanks.
@wmclennan77
amusleh
14 Mar 2022, 08:58
Hi,
You can use the loaded Bars BarOpened event instead of Bot OnBar method, ex:
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
public class AFFS : Robot
{
[Parameter("Name", DefaultValue = "AFFS")]
public string _name { get; set; }
[Parameter("Start Hour", DefaultValue = 6.0)]
public double _starttime { get; set; }
[Parameter("Stop Hour", DefaultValue = 18.0)]
public double _stoptime { get; set; }
[Parameter("Max Lots", DefaultValue = 100.0, MinValue = 0.01, MaxValue = 1000.0)]
public double _maxlots { get; set; }
[Parameter("Starting Risk (%)", DefaultValue = 1.0, MinValue = 0.01, MaxValue = 100.0)]
public double _startingrisk { get; set; }
[Parameter("Risk Step (%)", DefaultValue = 1.0, MinValue = 0.01, MaxValue = 100.0)]
public double _riskstep { get; set; }
[Parameter("Take Profit", DefaultValue = 5.0, MinValue = 0.1, MaxValue = 100.0)]
public double _takeprofit { get; set; }
[Parameter("Stop Loss", DefaultValue = 10.0, MinValue = 0.1, MaxValue = 100.0)]
public double _stoploss { get; set; }
[Parameter("Safety (Pips)", DefaultValue = 3.0, MinValue = 0.1, MaxValue = 100.0)]
public double _safety { get; set; }
[Parameter("High/Low Timeframe", DefaultValue = "Daily")]
public TimeFrame _hltf { get; set; }
private Bars _hlbars;
private double _bullprice, _bearprice, _previoushigh, _previouslow, _maxunits, _activerisk;
private bool _todaybuy, _todaysell;
protected override void OnStart()
{
_hlbars = MarketData.GetBars(_hltf);
_hlbars.BarOpened += _hlbars_BarOpened;
_safety *= Symbol.PipSize;
}
private void _hlbars_BarOpened(BarOpenedEventArgs obj)
{
var _currenthours = Server.Time.TimeOfDay.TotalHours;
bool _tradetime = _starttime < _stoptime ? _currenthours > _starttime && _currenthours < _stoptime : _currenthours < _stoptime || _currenthours > _starttime;
_activerisk = GetRisk();
var _volume = GetVolume();
_maxunits = Symbol.QuantityToVolumeInUnits(_maxlots);
if (_volume > _maxunits)
{
_volume = _maxunits;
}
_previoushigh = _hlbars.HighPrices.Last(1);
_previouslow = _hlbars.LowPrices.Last(1);
_bullprice = Symbol.Ask + _safety;
_bearprice = Symbol.Bid - _safety;
if (_tradetime && !_todaybuy)
{
if (_bullprice > _previoushigh)
{
ExecuteMarketOrder(TradeType.Buy, Symbol.Name, _volume, _name, _stoploss, _takeprofit);
_todaybuy = true;
}
}
if (!_tradetime && _todaybuy)
{
_todaybuy = false;
}
if (_tradetime && !_todaysell)
{
if (_bearprice < _previouslow)
{
ExecuteMarketOrder(TradeType.Sell, Symbol.Name, _volume, _name, _stoploss, _takeprofit);
_todaysell = true;
}
}
if (!_tradetime && _todaysell)
{
_todaysell = false;
}
}
private double GetRisk()
{
double _result = 0.0;
double _maxrisk = 10.0;
var _lastposition = History.FindLast(_name);
bool _win = _lastposition != null && _lastposition.NetProfit > 0.0 ? true : false;
if (_win && _activerisk < _maxrisk)
{
_result = _activerisk + _riskstep;
}
else if (!_win)
{
_result = _startingrisk;
}
return _result;
}
private double GetVolume()
{
double costPerPip = (double)((int)(Symbol.PipValue * 10000000)) / 100;
double baseNumber = Account.Balance;
double sizeInLots = Math.Round((baseNumber * _activerisk / 100) / (_stoploss * costPerPip), 2);
var result = Symbol.QuantityToVolumeInUnits(sizeInLots);
if (result > Symbol.VolumeInUnitsMax)
{
result = Symbol.VolumeInUnitsMax;
}
else if (result < Symbol.VolumeInUnitsMin)
{
result = Symbol.VolumeInUnitsMin;
}
else if (result % Symbol.VolumeInUnitsStep != 0)
{
result = result - (result % Symbol.VolumeInUnitsStep);
}
return result;
}
}
}
This way the execution logic will be executed only once per bar based on your selected time frame.
@amusleh
amusleh
10 Mar 2022, 10:16
Hi,
Try this:
@amusleh