Category Other  Published on 27/03/2024

cTrader HMA, SMA Multi-timeframe cBot

Description

This cTrader Hull & Simple Moving Average multi-timeframe strategy contains the full source code, it is for educational purposes to help traders with various levels of programming knowledge learn the following skills using Microsoft C# and the cTrader API.

  1. Define cBot parameters.
  2. How to apply multi-timeframe indicators.
  3. Execute trades based on trade rules.
  4. Apply risk management.
  5. Send Telegram alerts.

This cBot was created by the ClickAlgo Strategy Building Tool in a few minutes with no coding.

 

 

cTrader Algo Strategy Builder

You can download the Algo Strategy Builder and start creating your strategies, it can also be used to create a system that will send Telegram signals.

 

Watch Video Demo's

Watch a video demonstration of a multi-timeframe Relative Strength Index Strategy complete with source code, with no coding experience.

 

Need Modifications?

You can contact our development team if you need to add additional indicators or features to this cBot.

If you also would like us to convert your ideas or manual strategy into an automated system, we can help

 

A black text with a white background

Description automatically generated

ClickAlgo is a leading supplier of cTrader cBots & indicators.

 

DISCLAIMER

This product is for educational use only and should not be considered financial advice. Trading and Investing Activities are Inherently Risky, and Users of Our Material Should Be Prepared to Incur Losses in Connection with Such Activities.


using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

/*
   This code was created using the Algo Strategy Building Tool by ClickAlgo Limited
   https://clickalgo.com/strategy-builder
 
   This cBot does not guarantee any particular outcome or
   profit of any kind. Use it at your own risk.

   Created: 26/03/2024
   Name: HMA, SMA Multi-timeframe

   This strategy uses a 1-hour Hull & Simple Moving Average indicator together with a daily 1-day Hull Moving Average indicator for confirmation.
   
   DISCLAIMER
   ==========

   This product is for educational use only and should not be considered financial advice. 
   Trading and Investing Activities are Inherently Risky, and Users of Our Material Should Be Prepared to Incur Losses in Connection with Such Activities.
   
   NEED CODING HELP?
   ================
   
   IF YOU NEED ANY HELP CONTACT US: https://clickalgo.com/contact-development
*/

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None)]
    public class AlgoBuilderBot : Robot
    {
        // user parameter settings

        [Parameter("Quantity (Lots)", Group = "Protection", DefaultValue = 0.01, MinValue = 0.01, Step = 0.01)]
        public double Quantity { get; set; }

        [Parameter("Stop loss", Group = "Protection", DefaultValue = 100)]
        public int StopLoss { get; set; }

        [Parameter("Take profit", Group = "Protection", DefaultValue = 25)]
        public int TakeProfit { get; set; }

        [Parameter("Max Spread", Group = "Protection", DefaultValue = 5, MinValue = 0.0)]
        public double MaxSpread { get; set; }

        [Parameter("Trigger (pips)", Group = "Trailing Stop Loss", DefaultValue = 25)]
        public int TrailingStopTrigger { get; set; }
        
        [Parameter("Step (pips)", Group = "Trailing Stop Loss", DefaultValue = 5)]
        public int TrailingStopStep { get; set; }

        [Parameter("Bot Token", Group = "Telegram Alert", DefaultValue = "sdfsdfsdwf34wet34t")]
        public string BotToken { get; set; }

        [Parameter("Chat ID", Group = "Telegram Alert", DefaultValue = "345325325")]
        public string ChatID { get; set; }

        // Indicator settings for bullish signals

        [Parameter("Timeframe", DefaultValue = "h1", Group = "Bullish HMA Buy #1")]
        public TimeFrame HmaTimeFrameBuy1 { get; set; }
        
        [Parameter("HMA Periods", DefaultValue =  14, Group = "Bullish HMA Buy #1")]
        public int HmaPeriodsBuy1 { get; set; }

        [Parameter("Timeframe", DefaultValue = "h1", Group = "Bullish SMA Buy #2")]
        public TimeFrame SmaTimeFrameBuy2 { get; set; }
        
        [Parameter("SMA Periods", DefaultValue =  50, Group = "Bullish SMA Buy #2")]
        public int SmaPeriodsBuy2 { get; set; }

        [Parameter("Timeframe", DefaultValue = "D1", Group = "Bullish HMA Buy #3")]
        public TimeFrame HmaTimeFrameBuy3 { get; set; }
        
        [Parameter("HMA Periods", DefaultValue =  14, Group = "Bullish HMA Buy #3")]
        public int HmaPeriodsBuy3 { get; set; }

        // Indicator settings for bearish signals

        [Parameter("Timeframe", DefaultValue = "h1", Group = "Bearish HMA Sell #1")]
        public TimeFrame HmaTimeFrameSell1 { get; set; }
        
        [Parameter("HMA Periods", DefaultValue =  14, Group = "Bearish HMA Sell #1")]
        public int HmaPeriodsSell1 { get; set; }

        [Parameter("Timeframe", DefaultValue = "D1", Group = "Bearish HMA Sell #2")]
        public TimeFrame HmaTimeFrameSell2 { get; set; }
        
        [Parameter("HMA Periods", DefaultValue =  14, Group = "Bearish HMA Sell #2")]
        public int HmaPeriodsSell2 { get; set; }

        [Parameter("Timeframe", DefaultValue = "h1", Group = "Bearish SMA Sell #3")]
        public TimeFrame SmaTimeFrameSell3 { get; set; }
        
        [Parameter("SMA Periods", DefaultValue =  50, Group = "Bearish SMA Sell #3")]
        public int SmaPeriodsSell3 { get; set; }

        // declaring the standard bullish indicators

        private HullMovingAverage _hma_Buy1;
        private SimpleMovingAverage _sma_Buy2;
        private HullMovingAverage _hma_Buy3;

        // declaring the standard bearish indicators

        private HullMovingAverage _hma_Sell1;
        private HullMovingAverage _hma_Sell2;
        private SimpleMovingAverage _sma_Sell3;

        // declaring the market data variables for bullish signals.

        private Bars _hmaBars_Buy1;
        private Bars _smaBars_Buy2;
        private Bars _hmaBars_Buy3;

        // declaring the market data variables for bearish signals.

        private Bars _hmaBars_Sell1;
        private Bars _hmaBars_Sell2;
        private Bars _smaBars_Sell3;

        // Private fields.

        private string StrategyName { get; set; }

        // makes sure only 1 trade opens per signal
        bool IsBullish { get; set; }
        bool IsBearish { get; set; }    

        // Initialise variables when the cBot starts.

        protected override void OnStart()
        {
            StrategyName = "HMA, SMA Multi-timeframe";

            // constructing the market data for the bullish indicators
            _hmaBars_Buy1 = MarketData.GetBars(HmaTimeFrameBuy1);
            _smaBars_Buy2 = MarketData.GetBars(SmaTimeFrameBuy2);
            _hmaBars_Buy3 = MarketData.GetBars(HmaTimeFrameBuy3);

            // constructing the market data for the bearish indicators
            _hmaBars_Sell1 = MarketData.GetBars(HmaTimeFrameSell1);
            _hmaBars_Sell2 = MarketData.GetBars(HmaTimeFrameSell2);
            _smaBars_Sell3 = MarketData.GetBars(SmaTimeFrameSell3);

            // constructing the BULLISH indicators
            _hma_Buy1 = Indicators.HullMovingAverage(_hmaBars_Buy1.ClosePrices, HmaPeriodsBuy1);
            _sma_Buy2 = Indicators.SimpleMovingAverage(_smaBars_Buy2.ClosePrices, SmaPeriodsBuy2);
            _hma_Buy3 = Indicators.HullMovingAverage(_hmaBars_Buy3.ClosePrices, HmaPeriodsBuy3);

            // constructing the BEARISH indicators
            _hma_Sell1 = Indicators.HullMovingAverage(_hmaBars_Sell1.ClosePrices, HmaPeriodsSell1);
            _hma_Sell2 = Indicators.HullMovingAverage(_hmaBars_Sell2.ClosePrices, HmaPeriodsSell2);
            _sma_Sell3 = Indicators.SimpleMovingAverage(_smaBars_Sell3.ClosePrices, SmaPeriodsSell3);
        }

        // The onTick method is called on each price change.
        protected override void OnTick()
        {
            SetTrailingStop();
        }

         // this method is called when the candle closes and is used to check the trade signals, execute trades and send alerts.
        protected override void OnBarClosed()
        {
            TradeRulesBullish();            
            TradeRulesBearish();
        }

        // parent method to check rules and open bullish trade or send signal.
        private void TradeRulesBullish()
        {
            // flag to open a trade if all rules true.
            bool OpenBuyTrade = false;

            if (IsBullishSignal())
            {
                OpenBuyTrade = true;
            }
 
            if (OpenBuyTrade)
            {
                if (!IsBullish)
                {
                    if (!IsTradeOpen(TradeType.Buy))
                    {
                        OpenTrade(TradeType.Buy);
                    }

                    SendTradeAlerts(TradeType.Buy);
                }

                IsBullish = true;
            }
            else
            {
                IsBullish = false;

                CloseTrade(TradeType.Buy);
             }
        }


        // parent method to check rules and open bearish trade or send signal.
        private void TradeRulesBearish()
        {
            // flag to open a trade if all rules true.
            bool OpenSellTrade = false;

           if (IsBearishSignal())
            {
                OpenSellTrade = true;
            }

            if (OpenSellTrade)
            {
                if (!IsBearish)
                {
                    if (!IsTradeOpen(TradeType.Sell))
                    {
                        OpenTrade(TradeType.Sell);
                    }

                    SendTradeAlerts(TradeType.Sell);
                }

                IsBearish = true;
            }
            else
            {
                IsBearish = false;

                CloseTrade(TradeType.Sell);
            }
        }

        // returns true if all signals are bullish
        private bool IsBullishSignal() 
        {
            if (Symbol.Bid < _hma_Buy1.Result.LastValue)
            {
                return false;
            }

            if (Symbol.Bid < _sma_Buy2.Result.LastValue)
            {
                return false;
            }

            if (Symbol.Bid < _hma_Buy3.Result.LastValue)
            {
                return false;
            }

            return true;
        }

        // returns true if all signals are bearish
        private bool IsBearishSignal() 
        {
            if (Symbol.Ask > _hma_Sell1.Result.LastValue)
            {
                return false;
            }

            if (Symbol.Ask > _hma_Sell2.Result.LastValue)
            {
                return false;
            }

            if (Symbol.Ask > _sma_Sell3.Result.LastValue)
            {
                return false;
            }

            return true;
        }

        private double GetSpread()
        {
            var spread = (Symbol.Ask - Symbol.Bid) / Symbol.PipSize;
            return spread;
        }

        private void OpenTrade(TradeType type)
        {
            if(GetSpread() > MaxSpread)
            {
                Print("No trade opened due to spread being greater than maximum allowed.");
                return;
            }

            // calculate volume from lots
            var volume = Symbol.QuantityToVolumeInUnits(Quantity);
            volume = Symbol.NormalizeVolumeInUnits(volume, RoundingMode.Down);

            ExecuteMarketOrder(type, SymbolName, volume, StrategyName, StopLoss, TakeProfit);
        }

        // returns true if buy trade is open.
        private bool IsTradeOpen(TradeType type)
        {
            var positions = Positions.FindAll(StrategyName, SymbolName, type);
            if (positions.Count() > 0)
            {
                return true;
            }
            else return false;
        }

        // closes the trade with the opposite signal.
        private void CloseTrade(TradeType type)
        {
            var positions = Positions.FindAll(StrategyName, SymbolName, type);
            foreach (var position in positions)
            {
                position.Close();
            }
        }


        private void SetTrailingStop()
        {
            var sellPositions = Positions.FindAll(StrategyName, SymbolName, TradeType.Sell);

            foreach (Position position in sellPositions)
            {
                double distance = position.EntryPrice - Symbol.Ask;

                if (distance < 25 * Symbol.PipSize)
                    continue;

                double newStopLossPrice = Symbol.Ask + 5 * Symbol.PipSize;

                if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                }
            }

            var buyPositions = Positions.FindAll(StrategyName, SymbolName, TradeType.Buy);

            foreach (Position position in buyPositions)
            {
                double distance = Symbol.Bid - position.EntryPrice;

                if (distance < 25 * Symbol.PipSize)
                    continue;

                double newStopLossPrice = Symbol.Bid - 5 * Symbol.PipSize;
                if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                }
            }
        }

        // this method manages sending trade alerts
        private void SendTradeAlerts(TradeType type)
        {
            if (IsBacktesting)
            {
                return;
            }

            string direction = "Bullish";

            if (type == TradeType.Sell)
            {
                direction = "Bearish";
            }
            
            // send Telegram
            var Token = BotToken;
            var message = direction + " alert on " + SymbolName + " with " + TimeFrame.ToString();

            var result = Http.Get($"https://api.telegram.org/bot{Token}/sendMessage?chat_id={ChatID}&text={message}");

            // the following error codes may be incorrect and need updating.
            switch (result.StatusCode)
            {
                case 0:
                    Print("Telegram bot sleeping, wake it up.");
                    break;

                case 200:
                    Print("Telegram sent");
                    break;

                case 400:
                    Print("The chat id is incorrect.");
                    break;

                case 401:
                    Print("The bot token is incorrect.");
                    break;

                case 404:
                    Print("The bot token or chat id is missing or incorrect.");
                    break;

                default:
                    Print("unknown error code: " + result.StatusCode);
                    break;
            }

            // show popup
            MessageBox.Show(direction + " alert on " + SymbolName + " with " + TimeFrame.ToString(), StrategyName);
        }
    }
}

ClickAlgo's avatar
ClickAlgo

Joined on 05.02.2015

  • Distribution: Free
  • Language: C#
  • Trading platform: cTrader Automate
  • File name: HMA, SMA Multi-timeframe.algo
  • Rating: 0
  • Installs: 329
  • Modified: 27/03/2024 06:46
Comments
Log in to add a comment.
No comments found.