• cBot Coding
  • New to Coding - Need Help With Hull Moving Averages

I have used many indicators since I started trading and off course all of us. I came across one video explaining the Hull Moving Average and honestly, since nearly 1 year, i'm stick with it for my Buy Signal. I have changed couple of settings and now I'm sticking with those settings on any time frame. For Buy only as I'm a Buy Person only... No short trades., but it provides a glace of where the pricing is retracing and where you have to buy:

Three HMA:
21-HMA - Yellow
9-HMA - Orange
100-HMA Light Blue.

Also, add the default EMA-Cross Over and change the default settings to be:
Short-Length - 9
Long MA Length 21
In the Style, remove the short and Long MA lines and keep only the Cross with your preferred color.

Also, add default MACD for extra confirmation.

How it works.
It works on any time frame, when you have both 21 and 9 HMA cross-over, the EMA-Cross will print the signal and when you switch to a different timeframe, the 100 HMA is calling the price up.

For instance, a Trade on Gold today 8-9th Oct 2024

Buy Entry on 4hrs, Condition

MACD is -8.56-7.49 and sloop, and both lines Fast and Slow length, are about to Cross-over and histogram is shirking the bearish volume to bullish volume as the color is changing from Red to Pink.
HMA-21 and HMA-9 Crossed-Over already
HMA-100 is calling the price to 2627 - 2631
Buy Entry Price 2604.39 TP'ed 2624 - 2627

I use the same conditions for the lower timeframe, and it worked really well.

I'm interested to create a cBot, and I used ChatGPT to help me with that, but didn't provide enough details or code same as what I'm using in TradingView as Pine Code.

Any help on develops this as a cBot?



Thanks,

Thank you very much for your support. Let me try it and I will explore the strategy builder as well, provided the strategy builder supports the HMA curving and calculations.

Hello All,
I spent the weekend just learning about this cool thing, and I came across the cTrader Strategy Builder, which really helps at least to produce some codes.

I started modifying the codes from one to another just to understand, but I'm not really sure if I'm doing the correct thing or not as I have applied some of the ideas I used for my Powershell scrips.

I started to run the bot, and it looks like it provides great results as per the backtesting I did.

The best result I got is for the 10 and 15 minutes, I was impressed of the result %..

I forgot to add the code I used.
Any suggestions or improvements?

using System;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{

[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class HullMAAlgo : Robot
{
private HullMovingAverage hma9;
private HullMovingAverage hma21;
private HullMovingAverage hma100;

protected override void OnStart()
{
    // Initialize indicators
    hma9 = Indicators.HullMovingAverage(MarketData.GetSeries(TimeFrame).Close, 9);
    hma21 = Indicators.HullMovingAverage(MarketData.GetSeries(TimeFrame).Close, 21);
    hma100 = Indicators.HullMovingAverage(MarketData.GetSeries(TimeFrame).Close, 100);
}

protected override void OnBar()
{
    // Check for crossover conditions
    bool crossover = hma9.Result.Last(1) > hma21.Result.Last(1) && hma9.Result.Last(2) <= hma21.Result.Last(2);
    bool priceAboveHMAs = MarketSeries.Close.Last(1) > hma9.Result.Last(1) && MarketSeries.Close.Last(1) > hma21.Result.Last(1);
    bool priceBelowHMA100 = MarketSeries.Close.Last(1) < hma100.Result.Last(1);
  
    if (crossover && priceAboveHMAs && priceBelowHMA100)
    {
        // Calculate stop loss and take profit
        double stopLossPrice = MarketSeries.Close.Last(1) - 60 * Symbol.PipSize;
        double takeProfitPrice = hma100.Result.Last(1); // Target price at HMA100

        // Execute buy order
        ExecuteMarketOrder(TradeType.Buy, Symbol, 100, "HMA Crossover", stopLossPrice, takeProfitPrice);
    }
    }
}

}

This is 4 min back test between 3 June 2024 to 12 oct 2024

I have modified the code a bit "basically, playing around to see more results based on additional conditions"...

I'm a bit struggling in getting the minimum stoplosspips activiated in this code...

Also, added a trade protection just to confirm of trades to be taken...

So far I can see great win rate of this code...

Any suggestion / advise, would be highly appreciated.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{

[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class HullMAAlgo : Robot
{
private HullMovingAverage hma9;
private HullMovingAverage hma21;
private HullMovingAverage hma100;

[Parameter("Volume (in units)", DefaultValue = 1)]
public int Volume { get; set; }

    [Parameter("Stop Loss (in pips)", DefaultValue = 1)]
    public int StopLossPips { get; set; }

    [Parameter("Take Profit (in pips)", DefaultValue = 2)]
    public int TakeProfitPips { get; set; }

protected override void OnStart()
{
// Initialize indicators
hma9 = Indicators.HullMovingAverage(MarketData.GetSeries(TimeFrame).Close, 9);
hma21 = Indicators.HullMovingAverage(MarketData.GetSeries(TimeFrame).Close, 21);
hma100 = Indicators.HullMovingAverage(MarketData.GetSeries(TimeFrame).Close, 100);
}

protected override void OnBar()
{
// Check for crossover conditions
bool crossover = hma9.Result.Last(1) > hma21.Result.Last(1) && hma9.Result.Last(2) <= hma21.Result.Last(2);
bool priceAboveHMAs = MarketSeries.Close.Last(1) > hma9.Result.Last(1) && MarketSeries.Close.Last(1) > hma21.Result.Last(1) && MarketSeries.Close.Last(1) > hma100.Result.Last(1);
bool priceBelowHMA100 = MarketSeries.Close.Last(1) > hma100.Result.Last(1);
bool priceBelowHMA9 = MarketSeries.Close.Last(1) > hma9.Result.Last(1) && MarketSeries.Close.Last(0) > hma9.Result.Last(0);
if (crossover && priceAboveHMAs && priceBelowHMA100 && priceBelowHMA9)
{
// Check if the price crosses above the HMA
// if (MarketSeries.Close.Last(1) < hma9.Result.Last(1) && MarketSeries.Close.Last(0) > hma9.Result.Last(0))
{


    // Calculate stop loss and take profit
    //double stopLossPrice = MarketSeries.Close.Last(1) -100 * Symbol.PipSize;
    //double takeProfitPrice = hma100.Result.Last(1); // Target price at HMA100
    // Ensure no existing buy position
        //if (Positions.Find("Buy") == null)
    
    {
                double entryPrice = Symbol.Ask;
                double stopLossPrice = entryPrice - StopLossPips  * Symbol.PipSize;
                double takeProfitPrice = entryPrice + TakeProfitPips * Symbol.PipSize;

                // Execute market order
                ExecuteMarketOrder(TradeType.Buy, Symbol, Volume, "Buy", stopLossPrice, takeProfitPrice);
                Print("Buy order executed at price: {0}, SL: {1}, TP: {2}", entryPrice, stopLossPrice, takeProfitPrice);
            }

    // Execute buy order
   // ExecuteMarketOrder(TradeType.Buy, Symbol, 100, "HMA Crossover", stopLossPrice, takeProfitPrice);
}
}

}
}
}

a month later

Hello All,
I’m glad to hear that the strategy has been working well, especially for buy entries in a bull market. The added protection logic to pause trading during excessive losses is an important safeguard for account protection, which is great for preventing further drawdowns during unfavorable market conditions.

This strategy certainly seems like a solid starting point for any trader who is enthusiastic about Hull Moving Averages. The combination of HMA crossovers, price positioning relative to Hull MAs, and the RSI filter is a great way to identify high-quality buy entries.

Key Features of the Code:
Hull Moving Averages (HMA):

Using multiple Hull Moving Averages (9, 21, and 100) is a solid method for identifying trend direction and momentum. The crossover strategy between HMA9 and HMA21 will allow the robot to enter trades when momentum is shifting in the market.
RSI Filtering:

RSI is used to confirm that the market is not overbought, reducing the likelihood of entering at the top of an uptrend. With RSI conditions set below the oversold level, it filters out potential overbought conditions and helps avoid buy entries when the market is too strong or too weak.
Trade Protection Mechanisms:

Pause Trading on Excessive Losses: If the account experiences too many losses, the strategy pauses trading for a specified duration. This is a good risk management feature to avoid excessive drawdowns.
Stop-Loss and Take-Profit Levels: The fixed pips stop loss and take profit levels offer a clear exit strategy for each trade, ensuring consistent risk management.
Trailing Stop Logic: The trailing stop logic allows the bot to lock in profits as the market moves in favor of the position. This adds a dynamic aspect to risk management.
Position Limits and Loss Tracking:

By limiting the number of active positions and monitoring the performance of current trades (buy positions only), the strategy avoids overexposing the account to risk. The system intelligently ensures that only a certain number of positions can be opened at once, adding a layer of protection.
Possible Improvements or Extensions:
While the code is well-structured, a few areas that could be worth testing or adjusting (depending on your future goals or market conditions) are:

Sell Conditions (for a more balanced approach):
If you ever want to optimize the strategy further to trade in both directions (long and short), revisiting the sell conditions with additional filters or a distinct set of entry rules could help balance the strategy’s profitability.

Additional Filters/Indicators:
You could experiment with other indicators like the MACD or Bollinger Bands to complement the Hull MAs and RSI for more robust entry and exit signals.

Dynamic Lot Size:
Rather than using a fixed lot size, you could introduce a risk-based position sizing approach where the lot size is dynamically calculated based on the current account balance and risk tolerance (e.g., risking 1% of the account balance per trade).

Backtesting & Optimization:
Continuously backtest this strategy on different timeframes and market conditions to fine-tune parameters such as stop loss, take profit, trailing stops, and RSI levels.

`

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class HullMAAlgo : Robot

    {
        private HullMovingAverage hma9;
        private HullMovingAverage hma21;
        private HullMovingAverage hma100;
        private RelativeStrengthIndex rsi;

        // Define order parameters
        [Parameter("Lot Size", DefaultValue = 3)]
        public double LotSize { get; set; }

        [Parameter("Stop Loss (pips)", DefaultValue = 50)]
        public double StopLossPips { get; set; }

        [Parameter("Take Profit (pips)", DefaultValue = 100)]
        public double TakeProfitPips { get; set; }

        [Parameter("Trailing Stop (pips)", DefaultValue = 20)]
        public double TrailingStopPips { get; set; }

        [Parameter("RSI Period", DefaultValue = 14)]
        public int RsiPeriod { get; set; }

        [Parameter("RSI Overbought Level", DefaultValue = 70)]
        public double RsiOverbought { get; set; }

        [Parameter("RSI Oversold Level", DefaultValue = 30)]
        public double RsiOversold { get; set; }

        private DateTime lastTradeTime;
        private double totalLosses;
        private bool isTradingPaused;
        private DateTime pauseEndTime;

        protected override void OnStart()
        {
            // Initialize indicators
            hma9 = Indicators.HullMovingAverage(MarketData.GetSeries(TimeFrame).Close, 9);
            hma21 = Indicators.HullMovingAverage(MarketData.GetSeries(TimeFrame).Close, 21);
            hma100 = Indicators.HullMovingAverage(MarketData.GetSeries(TimeFrame).Close, 100);
            rsi = Indicators.RelativeStrengthIndex(MarketData.GetSeries(TimeFrame).Close, RsiPeriod);
            lastTradeTime = DateTime.UtcNow;
            totalLosses = 0;
            isTradingPaused = false;
        }

        protected override void OnBar()
        {
            if (isTradingPaused)
            {
                if (DateTime.UtcNow >= pauseEndTime)
                {
                    isTradingPaused = false;
                    totalLosses = 0; // Reset losses after pause
                    Print("Trading resumed.");
                }
                else
                {
                    return; // Exit if still in pause
                }
            }

            // Check for crossover conditions
            bool crossover = hma9.Result.Last(1) > hma21.Result.Last(1) && hma9.Result.Last(2) <= hma21.Result.Last(2);
            bool priceAboveHMAs = MarketSeries.Close.Last(1) > hma9.Result.Last(1);
            bool priceBelowHMA100 = MarketSeries.Close.Last(1) < hma100.Result.Last(1);
            bool rsiConditions = rsi.Result.Last(1) < RsiOversold;

            var totalPositions = Positions.FindAll("Buy", Symbol).Length;

            // Implement loss tracking
            double totalProfit = 0;
            foreach (var position in Positions.FindAll("Buy", Symbol))
            {
                totalProfit += position.GrossProfit;
                if (position.GrossProfit < 0)
                {
                    totalLosses += -position.GrossProfit; // Accumulate losses
                   
                }
            }
               

            // Check if trading should be paused
           if (DateTime.UtcNow - lastTradeTime > TimeSpan.FromHours(8) && totalLosses >= 100)
           {
                isTradingPaused = true;
                pauseEndTime = DateTime.UtcNow.AddHours(3);
                Print("Trading paused due to excessive losses. This method is made to enhance the account equity protection.");
                return;
            }



            // Check if conditions for entry are met
            if (crossover && priceAboveHMAs && priceBelowHMA100 && totalPositions < 5)
            {
                // Prevent trading if two out of three trades are losing
                if (totalPositions == 3)
                {
                    int losingCount = 0;
                    foreach (var position in Positions.FindAll("Buy", Symbol))
                    {
                        if (position.GrossProfit < 0)
                            losingCount++;
                    }

                    if (losingCount >= 2)
                    {
                        Print("Trading paused due to 2 out of 3 trades being losing. This method is made to enhance the account equity protection.");
                        return;
                    }
                }

                // Calculate stop loss and take profit
                double stopLossPrice = MarketSeries.Close.Last(1) - StopLossPips * Symbol.PipSize;
                double takeProfitPrice = MarketSeries.Close.Last(1) + TakeProfitPips * Symbol.PipSize;

                // Execute buy order
                ExecuteMarketOrder(TradeType.Buy, Symbol, LotSize, "Buy", stopLossPrice, takeProfitPrice);
                lastTradeTime = DateTime.UtcNow; // Update last trade time
            }

            // Implement trailing stop logic
            foreach (var position in Positions.FindAll("Buy", Symbol.Name))
            {
                double newStopLossPrice = position.EntryPrice + TrailingStopPips * Symbol.PipSize;

                if (position.GrossProfit >= position.EntryPrice + newStopLossPrice)
                {
                    try
                    {
                        ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                        Print("Position Modified with Profits");
                    }
                    catch (Exception ex)
                    {
                        Print("Error modifying position: " + ex.Message);
                    }
                }
            }
        }
    }
}
ClickAlgo Limited - Copyright © 2025.
All rights reserved.
Privacy Policy | Cookies | Risk Disclosure
Trustpilot Reviews cTrader Support