Description
A friend gave me the following conditions to write a cBot. When I finished writing it, I discovered that all of these conditions never happened at the same time. >_<
Strategy Objective:
The TrendFollowerBot strategy is designed to follow market trends using a combination of several technical indicators. The goal is to take buy (long) or sell (short) positions based on signals generated by these indicators.
Indicators Used:
1. Moving Averages:
• EMA 50 (Exponential Moving Average)
• SMA 100 (Simple Moving Average)
• EMA 50 is used to identify the short-term trend, while SMA 100 is used for the long-term trend. A buy signal is generated when EMA 50 is above SMA 100, indicating an uptrend. Conversely, a sell signal is generated when EMA 50 is below SMA 100.
2. MACD (Moving Average Convergence Divergence):
• Used to identify changes in trend direction and strength. A buy signal is given when the MACD line (fast EMA) is above the Signal line (slow EMA), and vice versa for a sell signal.
3. Momentum:
• Measures the rate of price change. A high momentum level indicates a strong trend. The strategy uses a threshold of 100 to determine trend strength.
4. RSI (Relative Strength Index):
• A momentum indicator that measures the speed and change of price movements. An RSI below 30 indicates an oversold condition (buy potential), while an RSI above 70 indicates an overbought condition (sell potential).
5. CCI (Commodity Channel Index):
• A trend indicator that identifies overbought or oversold levels. The strategy considers a CCI below -100 for buying and above 100 for selling.
6. Stochastic:
• Measures overbought and oversold conditions. Thresholds of 20 (oversold) and 80 (overbought) are used to trigger buy or sell signals.
7. ADX (Average Directional Index):
• An indicator of trend strength. An ADX above 25 indicates a strong trend.
8. Ichimoku Cloud:
• Evaluates the price position relative to the Ichimoku cloud to confirm trend direction. The strategy buys when the price is above the cloud and sells when it is below.
Trading Rules:
• To Buy:
• EMA 50 must be above SMA 100.
• The MACD line must be above the Signal line.
• Momentum must be above 100.
• RSI must be below 30.
• CCI must be below -100.
• Stochastic K must be below 20.
• ADX must be above 25.
• Ichimoku indicates that the price is above the cloud.
• To Sell:
• EMA 50 must be below SMA 100.
• The MACD line must be below the Signal line.
• Momentum must be below 100.
• RSI must be above 70.
• CCI must be above 100.
• Stochastic K must be above 80.
• ADX must be above 25.
• Ichimoku indicates that the price is below the cloud.
Position Management:
• Opening a Position: The algorithm executes a buy or sell order when all conditions are met.
• Closing a Position: The position is closed if the price crosses the Ichimoku cloud in the direction opposite to the current trend.
This strategy is trend-focused and uses a combination of indicators to confirm signals before making trading decisions.
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using cAlgo.API.Indicators;
using System;
using System.Linq;
namespace cAlgo.Robots
{
[Robot(AccessRights = AccessRights.None, AddIndicators = true)]
public class Lmstore_bot : Robot
{
// Parameters for Moving Averages
[Parameter("EMA Period (Short-term)", Group = "1. EMA", DefaultValue = 50)]
public int EmaPeriod { get; set; }
[Parameter("SMA Period (Long-term)", Group = "1. EMA", DefaultValue = 100)]
public int SmaPeriod { get; set; }
[Parameter("MACD Fast Period", Group = "2. MACD", DefaultValue = 12)]
public int FastPeriod { get; set; }
[Parameter("MACD Slow Period", Group = "2. MACD", DefaultValue = 26)]
public int SlowPeriod { get; set; }
[Parameter("MACD Signal Period", Group = "2. MACD", DefaultValue = 9)]
public int SignalPeriod { get; set; }
[Parameter("Momentum Period", Group = "3. Momentum", DefaultValue = 14)]
public int MomentumPeriod { get; set; }
[Parameter("Momentum Level", Group = "3. Momentum", DefaultValue = 100)]
public double MomentumLevel { get; set; }
[Parameter("RSI Period", Group = "4. RSI", DefaultValue = 14)]
public int RsiPeriod { get; set; }
[Parameter("OverS Level", Group = "4. RSI", DefaultValue = 30)]
public double RsiOversold { get; set; }
[Parameter("OverB Level", Group = "4. RSI", DefaultValue = 70)]
public double RsiOverbought { get; set; }
[Parameter("CCI Period", Group = "5. CCI", DefaultValue = 20)]
public int CciPeriod { get; set; }
[Parameter("OverB Level", Group = "5. CCI", DefaultValue = 100)]
public double OverboughtLevel { get; set; }
[Parameter("OverS Level", Group = "5. CCI", DefaultValue = -100)]
public double OversoldLevel { get; set; }
[Parameter("Stochastic Periods", Group = "6. Stochastic K", DefaultValue = 14)]
public int StochasticPeriods { get; set; }
[Parameter("K Period", Group = "6. Stochastic K", DefaultValue = 3)]
public int KPeriod { get; set; }
[Parameter("D Period", Group = "6. Stochastic K", DefaultValue = 3)]
public int DPeriod { get; set; }
[Parameter("OverS Level", Group = "6. Stochastic K", DefaultValue = 20)]
public int OversoldK { get; set; }
[Parameter("OverB Level", Group = "6. Stochastic K", DefaultValue = 80)]
public int OverboughtK { get; set; }
[Parameter("Periods", DefaultValue = 14, Group = "7. ADX")]
public int Periods { get; set; }
[Parameter("ADXR Level", DefaultValue = 25, Group = "7. ADX")]
public int ADXRLevel { get; set; }
[Parameter("Tenkan Sen Periods", DefaultValue = 9, Group = "8. Ichimoku", MinValue = 1)]
public int TenkanSenPeriods { get; set; }
[Parameter("Kijun Sen Periods", DefaultValue = 26, Group = "8. Ichimoku", MinValue = 1)]
public int KijunSenPeriods { get; set; }
[Parameter("Senkou Span B Periods", DefaultValue = 52, Group = "8. Ichimoku", MinValue = 1)]
public int SenkouSpanBPeriods { get; set; }
[Parameter(" First Volume (Lots)", DefaultValue = 0.1, MinValue = 0.01)]
public double FirstVolume { get; set; }
[Parameter("Label", DefaultValue = "Lmstore_bot")]
public string Label { get; set; }
private ExponentialMovingAverage _ema;
private SimpleMovingAverage _sma;
private MacdCrossOver _macd;
private MomentumOscillator _momentum;
private RelativeStrengthIndex _rsi;
private CommodityChannelIndex _cci;
private StochasticOscillator _stochastic;
private AverageDirectionalMovementIndexRating _averageDirectionalMovementIndexRating;
private IchimokuKinkoHyo _ichimokuKinkoHyo;
private bool Buy_EMASMA; private bool Sell_EMASMA;
private bool Buy_MACD; private bool Sell_MACD;
private bool Buy_Momentum; private bool Sell_Momentum;
private bool Buy_RSI; private bool Sell_RSI;
private bool Buy_CCI; private bool Sell_CCI;
private bool Buy_StochasticK; private bool Sell_StochasticK;
private bool Buy_ADX; private bool Sell_ADX;
private bool Buy_Ichimoku; private bool Sell_Ichimoku;
private bool Close_Buy; private bool Close_Sell;
private bool IsBuyPositionOpen()
{
return Positions.Any(p => p.SymbolName == SymbolName && p.Label == Label && p.TradeType == TradeType.Buy);
}
private bool IsSellPositionOpen()
{
return Positions.Any(p => p.SymbolName == SymbolName && p.Label == Label && p.TradeType == TradeType.Sell);
}
protected override void OnStart()
{
_ema = Indicators.ExponentialMovingAverage(Bars.ClosePrices, EmaPeriod);
_sma = Indicators.SimpleMovingAverage(Bars.ClosePrices, SmaPeriod);
_macd = Indicators.MacdCrossOver(FastPeriod, SlowPeriod, SignalPeriod);
_momentum = Indicators.MomentumOscillator(Bars.ClosePrices, MomentumPeriod);
_rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, RsiPeriod);
_cci = Indicators.CommodityChannelIndex(CciPeriod);
_stochastic = Indicators.StochasticOscillator(StochasticPeriods, KPeriod, DPeriod, MovingAverageType.Simple);
_averageDirectionalMovementIndexRating = Indicators.AverageDirectionalMovementIndexRating(Periods);
_ichimokuKinkoHyo = Indicators.IchimokuKinkoHyo(TenkanSenPeriods, KijunSenPeriods, SenkouSpanBPeriods);
}
protected override void OnBar()
{
double emaValue = _ema.Result.LastValue;
double smaValue = _sma.Result.LastValue;
Buy_EMASMA = emaValue > smaValue; Sell_EMASMA = emaValue < smaValue;
var macdValue = _macd.Histogram.Last(1);
var macdSignalValue = _macd.Signal.Last(1);
Buy_MACD = macdValue > macdSignalValue; Sell_MACD = macdValue < macdSignalValue;
double previousMomentum = _momentum.Result.Last(1);
Buy_Momentum = previousMomentum > MomentumLevel; Sell_Momentum = previousMomentum < MomentumLevel;
double currentRsi = _rsi.Result.Last(0);
Buy_RSI = currentRsi < RsiOversold; Sell_RSI = currentRsi > RsiOverbought;
var currentCCI = _cci.Result.LastValue;
Buy_CCI = currentCCI < OversoldLevel; Sell_CCI = currentCCI > OverboughtLevel;
double currentStochasticK = _stochastic.PercentK.Last(0);
Buy_StochasticK = currentStochasticK < OversoldK; Sell_StochasticK = currentStochasticK > OverboughtK;
double currentADXR = _averageDirectionalMovementIndexRating.ADXR.Last(0);
Buy_ADX = currentADXR > ADXRLevel; Sell_ADX = currentADXR < ADXRLevel;
double currentIchimokuSpanB = _ichimokuKinkoHyo.SenkouSpanB.Last(0);
double currentIchimokuSpanA = _ichimokuKinkoHyo.SenkouSpanA.Last(0);
Buy_Ichimoku = Bars.ClosePrices.Last(0) > currentIchimokuSpanB && Bars.ClosePrices.Last(0) > currentIchimokuSpanA;
Sell_Ichimoku = Bars.ClosePrices.Last(0) < currentIchimokuSpanB && Bars.ClosePrices.Last(0) < currentIchimokuSpanA;
Close_Buy = Bars.ClosePrices.Last(0) < currentIchimokuSpanB && Bars.ClosePrices.Last(0) < currentIchimokuSpanA;
Close_Sell = Bars.ClosePrices.Last(0) > currentIchimokuSpanB && Bars.ClosePrices.Last(0) > currentIchimokuSpanA;
if (Buy_EMASMA && Buy_MACD && Buy_Momentum && Buy_RSI && Buy_CCI && Buy_StochasticK && Buy_ADX && Buy_Ichimoku ) // Check buy conditions
{
if (!IsBuyPositionOpen())
{
ExecuteMarketOrder(TradeType.Buy, SymbolName, Symbol.QuantityToVolumeInUnits(FirstVolume), Label);
}
}
if (Close_Buy)
{
ClosePositions(TradeType.Buy);
}
if (Sell_EMASMA && Sell_MACD && Sell_Momentum && Sell_RSI && Sell_CCI && Sell_StochasticK && Sell_ADX && Sell_Ichimoku) // Check sell conditions
{
if (!IsSellPositionOpen())
{
ExecuteMarketOrder(TradeType.Sell, SymbolName, Symbol.QuantityToVolumeInUnits(FirstVolume), Label);
}
}
if (Close_Sell)
{
ClosePositions(TradeType.Sell);
}
}
private void ClosePositions(TradeType tradeType) // Function to close specific positions by trade type
{
foreach (var position in Positions.FindAll(Label, SymbolName))
{
if (position.TradeType == tradeType)
{
ClosePosition(position);
}
}
}
}
}
ForexViet
Joined on 05.05.2023
- Distribution: Free
- Language: C#
- Trading platform: cTrader Automate
- File name: Lmstore_bot_withSourceCode.algo
- Rating: 0
- Installs: 451
- Modified: 30/08/2024 14:18
Comments
Thank you for your work. I’ll give it a try, and I hope it works well. If not, we’ll need to improve it. This is a strategy that works wonderfully, but the bot needs to function properly,
For the exit points, it’s when the price enters the cloud in the opposite direction of the position.
Among the indicators in this cbot, I only use RSI, and I don't know about the other indicators. But he asked me to help create a cbot with all of the above conditions happening at the same time, so I tried combining them to see what the results would be. If you want to know the cBot works, replace some of the && by ||, this will help test cbot.
not sure if i'd call ChatGPT a friend or not :D
but yeah, will be almost impossible for even a subset of those to align and fire in a trade.
Can be added the possibility to chose what indicators to be used? It's very hard to find a entry to be covered by all indicators in the same time.