Category Range  Published on 06/01/2015

RSI & Boll Bands w Threshold activation

Description
Reversion & Trend trading robot. Utilizes threshold to determine entry. Includes trailing stop loss.

Reversion & Trend trading robot. Utilizes threshold to determine entry. Includes trailing stop loss.


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

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class rsi_bol : Robot
    {
        [Parameter("Source")]
        public DataSeries Source { get; set; }
        [Parameter("lotsize", DefaultValue = 10000)]
        public int lotsize { get; set; }


        [Parameter("sl", DefaultValue = -16)]
        public int sl { get; set; }
        [Parameter("tp", DefaultValue = 18)]
        public int tp { get; set; }
        [Parameter("semiTrendSL", DefaultValue = -16)]
        public int semiTrendSL { get; set; }
        [Parameter("semiTrendTP", DefaultValue = 18)]
        public int semiTrendTP { get; set; }

        [Parameter("Period0", DefaultValue = 12)]
        public int Period0 { get; set; }

        [Parameter("Period1", DefaultValue = 18)]
        public int Period1 { get; set; }
        [Parameter("stdev", DefaultValue = 3)]
        public double stdev { get; set; }
        [Parameter("rsitop", DefaultValue = 67)]
        public int rsitop { get; set; }
        [Parameter("rsibottom", DefaultValue = 36)]
        public int rsibottom { get; set; }

        [Parameter("size", DefaultValue = 30)]
        public int size { get; set; }
        [Parameter("threshold", DefaultValue = 3.0)]
        public double threshold { get; set; }

        //Boundaries are percentages between 1 and -1 and be about 0
        [Parameter("upperbound", DefaultValue = 0.02)]
        public double upperbound { get; set; }
        [Parameter("lowerbound", DefaultValue = -0.02)]
        public double lowerbound { get; set; }

        [Parameter("Position Label", DefaultValue = "trend")]
        public string Label1 { get; set; }
        [Parameter("Position Label", DefaultValue = "rsibol")]
        public string Label2 { get; set; }

        //for trend
        [Parameter("Trigger (pips)", DefaultValue = 100)]
        public int Trigger { get; set; }
        [Parameter("Trailing Stop (pips)", DefaultValue = 50)]
        public int TrailingStop { get; set; }

        //for reversion
        [Parameter("reversion Trigger (pips)", DefaultValue = 100)]
        public int revTrigger { get; set; }
        [Parameter("reversion Trailing Stop (pips)", DefaultValue = 50)]
        public int revTrailingStop { get; set; }


        private bool _isTrigerred;

        private double[] BOL, oneBOL, twoBOL;
        private RelativeStrengthIndex rsi;
        private BollingerBands bol;

        protected override void OnStart()
        {

            rsi = Indicators.RelativeStrengthIndex(Source, Period0);
            bol = Indicators.BollingerBands(Source, Period1, stdev, MovingAverageType.Simple);

            //obtain high and low of initial start bar 
            double max = MarketSeries.High.LastValue;
            double min = MarketSeries.Low.LastValue;
        }

        protected override void OnTick()
        {

            //Computing objective/first order/second order derivative functions
            int oneSize = size - 1;
            int twoSize = oneSize - 1;

            BOL = new double[size];
            for (int i = 0; i < BOL.Length; i++)
            {
                BOL[i] = bol.Top.Last(i) - bol.Bottom.Last(i);
                //Print(BOL[i]);
            }
            //First derivative : Change in bollinger band value
            oneBOL = new double[oneSize];
            for (int i = 0; i < oneBOL.Length; i++)
            {
                //change in bollinger bands in % terms
                oneBOL[i] = BOL[i + 1] / BOL[0] - 1;
            }
            //Second derivative: Rate of change in bollinger band value
            twoBOL = new double[twoSize];
            for (int i = 0; i < twoBOL.Length; i++)
            {
                twoBOL[i] = oneBOL[i + 1] / oneBOL[i] - 1;
            }



            actual(BOL);
            gradientDifference(oneBOL);
//Reversion trading algo
            if (actual(BOL) > threshold && (gradientDifference(oneBOL) > upperbound || gradientDifference(oneBOL) < lowerbound))
            {
                if (rsi.Result.LastValue > rsitop && Symbol.Bid > bol.Top.LastValue)
                {
                    Open(TradeType.Sell);
                    //Close(TradeType.Buy);
                }
                else if (rsi.Result.LastValue < rsibottom && Symbol.Ask < bol.Bottom.LastValue)
                {
                    Open(TradeType.Buy);
                    //Close(TradeType.Sell);
                }
            }
//Semi trend trading algo
            if (gradientDifference(oneBOL) > upperbound || gradientDifference(oneBOL) < lowerbound)
            {
                //need to add close posn condition else will screw up
                if (Symbol.Ask > bol.Main.LastValue)
                {
                    trendOpen(TradeType.Buy);
                }
                if (Symbol.Bid < bol.Main.LastValue)
                {
                    trendOpen(TradeType.Sell);
                }

            }
            //trailing stoploss for trend
            var position = Positions.Find(Label1);

            if (position == null)
                return;

            if (position.TradeType == TradeType.Buy)
            {
                double distance = Symbol.Bid - position.EntryPrice;

                if (distance >= Trigger * Symbol.PipSize)
                {
                    if (!_isTrigerred)
                    {
                        _isTrigerred = true;
                        Print("Trailing Stop Loss triggered...");
                    }

                    double newStopLossPrice = Math.Round(Symbol.Bid - TrailingStop * Symbol.PipSize, Symbol.Digits);

                    if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
                    {
                        ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                    }
                }
            }
            else
            {
                double distance = position.EntryPrice - Symbol.Ask;

                if (distance >= Trigger * Symbol.PipSize)
                {
                    if (!_isTrigerred)
                    {
                        _isTrigerred = true;
                        Print("Trailing Stop Loss triggered...");
                    }

                    double newStopLossPrice = Math.Round(Symbol.Ask + TrailingStop * Symbol.PipSize, Symbol.Digits);

                    if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
                    {
                        ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                    }
                }
            }
            //for reversion
            var revPosition = Positions.Find(Label2);

            if (revPosition == null)
                return;

            if (revPosition.TradeType == TradeType.Buy)
            {
                double distance = Symbol.Bid - revPosition.EntryPrice;

                if (distance >= revTrigger * Symbol.PipSize)
                {
                    if (!_isTrigerred)
                    {
                        _isTrigerred = true;
                        Print("Trailing Stop Loss triggered...");
                    }

                    double newStopLossPrice = Math.Round(Symbol.Bid - revTrailingStop * Symbol.PipSize, Symbol.Digits);

                    if (revPosition.StopLoss == null || newStopLossPrice > revPosition.StopLoss)
                    {
                        ModifyPosition(revPosition, newStopLossPrice, revPosition.TakeProfit);
                    }
                }
            }
            else
            {
                double distance = revPosition.EntryPrice - Symbol.Ask;

                if (distance >= revTrigger * Symbol.PipSize)
                {
                    if (!_isTrigerred)
                    {
                        _isTrigerred = true;
                        Print("Trailing Stop Loss triggered...");
                    }

                    double newStopLossPrice = Math.Round(Symbol.Ask + revTrailingStop * Symbol.PipSize, Symbol.Digits);

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

        }
        protected override void OnBar()
        {

        }
        private void Close(TradeType tradeType)
        {
            foreach (var position in Positions.FindAll("rsibol", Symbol, tradeType))
                ClosePosition(position);
        }

        private void Open(TradeType tradeType)
        {
            var position = Positions.Find("rsibol", Symbol, tradeType);

            if (position == null)
                ExecuteMarketOrder(tradeType, Symbol, lotsize, "rsibol", sl, tp);
        }
        private void trendOpen(TradeType tradeType)
        {
            var position = Positions.Find("trend", Symbol, tradeType);

            if (position == null)
                ExecuteMarketOrder(tradeType, Symbol, lotsize, "trend", semiTrendSL, semiTrendTP);
        }

        private int LotScale(int lotsize)
        {
            //mod the inside.. from 0 onwards. return what value
            return 0;
        }

        //Compute pattern of top - bottom bollinger bands
        private double actual(double[] x)
        {
            double tot = 0.0;

            for (int i = 0; i < x.Length; i++)
            {
                tot += x[i];
            }
            double avg = tot / x.Length;
            return (avg);

        }
        private double gradientDifference(double[] x)
        {
            //Note: array values are in %, aim to sum to 0
            double sum = 0.0;

            for (int i = 0; i < x.Length; i++)
            {
                sum += x[i];
            }
            return (sum);
        }

        //Sample patterns

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }


    }
}


CH
chocoboy

Joined on 16.09.2014

  • Distribution: Free
  • Language: C#
  • Trading platform: cTrader Automate
  • File name: rsi_bol.algo
  • Rating: 1.67
  • Installs: 9065
  • Modified: 13/10/2021 09:55
Comments
Log in to add a comment.
DA
davidmwabuka · 1 year ago

dont discourage the poster. Just suggest better ways of improving. or improve by urselves

aimerdoux's avatar
aimerdoux · 9 years ago

lol you make two trailing stops two open methods too much code useless, you can parametrize the method with string label 

IR
ironmine · 9 years ago

Another useless robot which is impossible to set up, with five million obscure parameters and no description for them. It's also useless to ask questions at this forum, the authors of cBots do not care to answer them...

AY
aysos75 · 9 years ago

Why you don't precise the result of the bot with the parameters, the symbol and the timeframe ?

A bot without parameters, symbol and timeframe is incomplete!

KA
Kaworu · 9 years ago

just for reference, can you guys post your "winning" setup?

07
070455 · 9 years ago

Hi chocoboy

I am just testing the robot. it does what it should do - but: When it takes stoploss, it starts directly a new trade in the same direction. What parameter do i have to change, to start a new trade in the opposite direction?

THX

Martin

CH
chiripacha · 9 years ago

o.k. thks.

GO
goodtrades · 9 years ago
Hi i just changed the negative values so they are no longer negative.
CH
chiripacha · 9 years ago

Hi goodtrades,

could you please be so kind send me a copy of the now working code. I can't achieve no results. You could it post here or send it by email to:

chiripacha@yahoo.com.au

Thank you

 

 

GO
goodtrades · 9 years ago
HI Chocoboy - thanks. opennig trades fine now :)
CH
chocoboy · 9 years ago

none of the "sl" variables should be negative. The lower bound should be 0. 

You are prob getting that msg because whenever the bot tries to submit a trade, the negative "sl" values prevents it from doing so.

That should solve the problem.

 

 

 

GO
goodtrades · 9 years ago

Hi chocoboy - tried that, still getting the "invalid message"

CH
chocoboy · 9 years ago

Hm... You might want to try changing the value of the "lotsize" parameter?

 

 

GO
goodtrades · 9 years ago

Hi - unable to open orders. keep getting "invalid request" notifications