Standard Deviation "revert to mean" Bot
Standard Deviation "revert to mean" Bot
14 Jun 2022, 20:01
Hi,
I am interested in creating a bot that would enter both short and long positions based on a deviation away from a mean.
This is where I am so far... I am unsure how to get it read when it reaches a specified amount of deviations above or below the moving average.
Is there an indicator that can be applied into the parameters that will track this that I can optimize to being anywhere between 2 - 4 standard deviations away?
I would like it to enter short when it reaches a set distance above the moving average, and then long when it reaches a set distance below the moving average. Then have it exit either when it reverts back to that mean, or possibly (if it optimizes better this way) to have it exit when it reaches back to a specified standard deviation away.
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.EasternStandardTime, AccessRights = AccessRights.None)]
public class MADeviationBot : Robot
{
[Parameter("Instance Name", DefaultValue = "")]
public string InstanceName { get; set; }
[Parameter("Source")]
public DataSeries SourceSeries { get; set; }
[Parameter("MA Type")]
public MovingAverageType Type { get; set; }
[Parameter("MA Period")]
public int MAPeriod { get; set; }
[Parameter("Stop Loss")]
public int StopLoss { get; set; }
[Parameter("Risk %", MinValue = 0.01, Step = 0.01)]
public double RiskPerTrade { get; set; }
private MovingAverage MAtype;
protected override void OnStart()
{
MAtype = Indicators.MovingAverage(SourceSeries, MAPeriod, Type);
}
protected override void OnBar()
{
int index = Bars.Count - 1;
Entry(index);
Exits(index);
}
private void Entry(int index)
{
if (Bars.ClosePrices[index] < //-4 or optimized Standard Deviation below MAtype.Result )
{
ExecuteMarketOrder(TradeType.Buy, SymbolName, GetVolume(StopLoss), InstanceName, StopLoss, null);
}
}
if (Bars.ClosePrices[index] > //+4 or optimized Standard Deviation above MAtype.Result )
{
ExecuteMarketOrder(TradeType.Sell, SymbolName, GetVolume(StopLoss), InstanceName, StopLoss, null);
}
}
}
private void Exits(int index)
{
var positions = Positions.FindAll(InstanceName, SymbolName);
foreach (var position in positions)
if ((position.TradeType == TradeType.Buy && Bars.ClosePrices[index] > MAtype.Result) || (position.TradeType == TradeType.Sell && Bars.ClosePrices[index] < Matype.Result.Result[index]))
ClosePosition(position);
}
private double GetVolume(double? stopLossPips = null)
{
double costPerPip = (double)((int)(Symbol.PipValue * 10000000)) / 100;
// Change this to Account.Equity if you want to
double baseNumber = Account.Balance;
double sizeInLots = Math.Round((baseNumber * RiskPerTrade / 100) / (stopLossPips.Value * costPerPip), 1);
var result = Symbol.QuantityToVolumeInUnits(sizeInLots);
return result;
}
}
}
Replies
kurtisnauss
15 Jun 2022, 15:39
RE: Thank you, I will try that out and play around with it. There are other parameters I would like to add but needed that before anything.
amusleh said:
H,
You can use standard deviation indicator and a multiplier number like Bollinger Bands, example:
using System; using cAlgo.API; using cAlgo.API.Indicators; using cAlgo.API.Internals; namespace cAlgo.Robots { [Robot(TimeZone = TimeZones.EasternStandardTime, AccessRights = AccessRights.None)] public class MADeviationBot : Robot { [Parameter("Instance Name", DefaultValue = "")] public string InstanceName { get; set; } [Parameter("Source")] public DataSeries SourceSeries { get; set; } [Parameter("MA Type")] public MovingAverageType Type { get; set; } [Parameter("MA Period")] public int MAPeriod { get; set; } [Parameter("Stop Loss")] public int StopLoss { get; set; } [Parameter("Risk %", MinValue = 0.01, Step = 0.01)] public double RiskPerTrade { get; set; } [Parameter("Std Multiplier", DefaultValue = 1)] public double StdMultiplier { get; set; } private MovingAverage _ma; private StandardDeviation _standardDeviation; protected override void OnStart() { _ma = Indicators.MovingAverage(SourceSeries, MAPeriod, Type); _standardDeviation = Indicators.StandardDeviation(SourceSeries, MAPeriod, Type); } protected override void OnBar() { int index = Bars.Count - 1; Entry(index); Exits(index); } private void Entry(int index) { if (_ma.Result[index] - Bars.ClosePrices[index] > _standardDeviation.Result[index] * StdMultiplier) { ExecuteMarketOrder(TradeType.Buy, SymbolName, GetVolume(StopLoss), InstanceName, StopLoss, null); } else if (Bars.ClosePrices[index] - _ma.Result[index] > _standardDeviation.Result[index] * StdMultiplier) { ExecuteMarketOrder(TradeType.Sell, SymbolName, GetVolume(StopLoss), InstanceName, StopLoss, null); } } private void Exits(int index) { var positions = Positions.FindAll(InstanceName, SymbolName); foreach (var position in positions) { if ((position.TradeType == TradeType.Buy && Bars.ClosePrices[index] > _ma.Result[index]) || (position.TradeType == TradeType.Sell && Bars.ClosePrices[index] < _ma.Result[index])) { ClosePosition(position); } } } private double GetVolume(double? stopLossPips = null) { double costPerPip = (double)((int)(Symbol.PipValue * 10000000)) / 100; // Change this to Account.Equity if you want to double baseNumber = Account.Balance; double sizeInLots = Math.Round((baseNumber * RiskPerTrade / 100) / (stopLossPips.Value * costPerPip), 1); var result = Symbol.QuantityToVolumeInUnits(sizeInLots); return result; } } }
@kurtisnauss
amusleh
15 Jun 2022, 08:09
H,
You can use standard deviation indicator and a multiplier number like Bollinger Bands, example:
@amusleh