RSI & Boll Bands w Threshold activation free

by chocoboy in category Range at 06/01/2015
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.

Warning! Executing the following cBot may result in loss of funds. Use it at your own risk.
Notification Publishing copyrighted material is strictly prohibited. If you believe there is copyrighted material in this section you may use the Copyright Infringement Notification form to submit a claim.
Formula / Source Code
Language: C#
Trading Platform: cAlgo
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
        }


    }
}
Comments

goodtrades - January 12, 2015 @ 00:09

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

chocoboy - January 12, 2015 @ 09:54

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

 

 

goodtrades - January 12, 2015 @ 17:51

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

chocoboy - January 13, 2015 @ 16:55

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.

 

 

 

goodtrades - January 13, 2015 @ 17:12

HI Chocoboy - thanks. opennig trades fine now :)

chiripacha - January 15, 2015 @ 21:54

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

 

 

goodtrades - January 17, 2015 @ 05:39

Hi i just changed the negative values so they are no longer negative.

chiripacha - January 17, 2015 @ 21:46

o.k. thks.

070455 - June 11, 2015 @ 18:25

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

Kaworu - June 12, 2015 @ 22:53

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

aysos75 - June 20, 2015 @ 19:03

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!

ironmine - October 18, 2015 @ 11:58

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...

aimerdoux - November 01, 2015 @ 22:00

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

5