Hybrid Bot

Created at 23 Jul 2017, 08:02
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
TH

theonlinemick

Joined 23.07.2017

Hybrid Bot
23 Jul 2017, 08:02


Hi, I'd like to know if its possible to combine the following into a single algo...

//Fractal Indicator

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

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class FractalsTF : Indicator
    {

        [Parameter()]
        public TimeFrame FractalTimeFrame { get; set; }

        [Output("Top Fractal", Color = Colors.Red, PlotType = PlotType.Points, Thickness = 5)]
        public IndicatorDataSeries TopFractal { get; set; }

        [Output("Bottom Fractal", Color = Colors.Green, PlotType = PlotType.Points, Thickness = 5)]
        public IndicatorDataSeries BottomFractal { get; set; }

        protected MarketSeries _source;
        private int _lookback = 3;

        protected override void Initialize()
        {

            // Initialize and create nested indicators
            _source = this.MarketData.GetSeries(FractalTimeFrame);
        }

        public override void Calculate(int index)
        {
            DrawUpFractal(index, _lookback, TopFractal);
            DrawDownFractal(index, _lookback, BottomFractal);
        }

        protected void DrawUpFractal(int index, int period, IndicatorDataSeries series)
        {
            var sourceIdx = _source.OpenTime.GetIndexByTime(this.MarketSeries.OpenTime[index]);

            int highIdx = -1;
            double highPoint = double.MinValue;
            int cnt = 0;
            while (cnt < period)
            {
                int idx = sourceIdx - cnt;
                if (_source.High[idx] > highPoint)
                {
                    highPoint = _source.High[idx];
                    highIdx = idx;
                }
                cnt++;
            }
            if (_source.High[highIdx - 1] < highPoint && _source.High[highIdx + 1] < highPoint)
            {
                // We're scaling between timeframes, so we have to find the exact index
                // of the price on the chart timeframe.
                int outPutIdx = this.MarketSeries.OpenTime.GetIndexByTime(_source.OpenTime[highIdx]);
                double currerntHigh = this.MarketSeries.High[outPutIdx];
                while (currerntHigh != highPoint && outPutIdx < this.MarketSeries.High.Count)
                {
                    currerntHigh = this.MarketSeries.High[++outPutIdx];
                    series[outPutIdx] = double.NaN;
                }
                series[outPutIdx] = highPoint;
            }
        }

        protected void DrawDownFractal(int index, int period, IndicatorDataSeries series)
        {
            var sourceIdx = _source.OpenTime.GetIndexByTime(this.MarketSeries.OpenTime[index]);

            int lowIdx = -1;
            double lowPoint = double.MaxValue;
            int cnt = 0;
            while (cnt < period)
            {
                int idx = sourceIdx - cnt;
                series[idx] = double.NaN;
                if (_source.Low[idx] < lowPoint)
                {
                    lowPoint = _source.Low[idx];
                    lowIdx = idx;
                }
                cnt++;
            }
            if (_source.Low[lowIdx - 1] > lowPoint && _source.Low[lowIdx + 1] > lowPoint)
            {
                // We're scaling between timeframes, so we have to find the exact index
                // of the price on the chart timeframe.
                int outPutIdx = this.MarketSeries.OpenTime.GetIndexByTime(_source.OpenTime[lowIdx]);
                double currerntLow = this.MarketSeries.Low[outPutIdx];
                while (currerntLow != lowPoint && outPutIdx < this.MarketSeries.Low.Count)
                {
                    currerntLow = this.MarketSeries.Low[++outPutIdx];
                    series[outPutIdx] = double.NaN;
                }
                series[outPutIdx] = lowPoint;
            }
        }
    }
}

 

Using the above 'top' and 'bottem' fractal indicators to open buy/sell positions (5min charts, with 1hr fractaltimeframe overlay). 

I'd like it to use the martigale strategy only when the trade hits a negative stop loss, but take profit on 'bottem' fractal indicator.

To tweak it further... utilize the trade optimizer algo to step the SL behind the price...

//Trade optimizer

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


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



        Symbol currentSymbol;
        Position currentPosition;
        double? newStopLoss = 0;
        double? newTakeProfit = 0;


        [Parameter("Trigger (pips)", DefaultValue = 1.0, MinValue = 0)]
        public double TriggerPips { get; set; }

        [Parameter("Trail SL (pips)", DefaultValue = 1.0, MinValue = 0)]
        public double TrailSLPips { get; set; }

        [Parameter("Trail TP (pips)", DefaultValue = 5.0, MinValue = 0)]
        public double TrailTPPips { get; set; }

        [Parameter("Notify", DefaultValue = true)]
        public bool Notifiy { get; set; }


        [Parameter("Email Address")]
        public string EmailAddress { get; set; }


        protected override void OnStart()
        {


        }

        protected override void OnTick()
        {
            foreach (var pos in Positions)
            {
                this.currentSymbol = MarketData.GetSymbol(pos.SymbolCode);
                this.currentPosition = pos;
                if (isNearTarget())
                {

                    CalcNewValues();

                    AdjustPosition();

                    SendMail();
                }
            }
        }

        string BuildMessage()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("Tango Trade Optimizer modified your position:{0}", System.Environment.NewLine);
            sb.AppendFormat("Unr. Net:{0} {3} Stop Loss:{1}{3}  Take Profit:{2}", currentPosition.NetProfit, currentPosition.StopLoss, currentPosition.TakeProfit, System.Environment.NewLine);
            return sb.ToString();
        }

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

        void CalcNewValues()
        {
            if (currentPosition.TradeType == TradeType.Buy)
            {
                newStopLoss = currentSymbol.Bid - (this.currentSymbol.PipSize * this.TrailSLPips);
                newTakeProfit = currentSymbol.Bid + (this.currentSymbol.PipSize * this.TrailTPPips);
            }
            else
            {
                newStopLoss = currentSymbol.Ask + (this.currentSymbol.PipSize * this.TrailSLPips);
                newTakeProfit = currentSymbol.Ask - (this.currentSymbol.PipSize * this.TrailTPPips);
            }
        }



        void AdjustPosition()
        {
            if (newStopLoss == 0 || newTakeProfit == 0)
                return;
            ModifyPosition(currentPosition, newStopLoss, newTakeProfit);

        }

        void SendMail()
        {
            if (this.Notifiy)
                Notifications.SendEmail(this.EmailAddress, this.EmailAddress, "Tango Trade Optimizer", BuildMessage());

            Print("new values new SL:{0}- New TP{1}", newStopLoss, newTakeProfit);
        }



        bool isNearTarget()
        {

            if (this.currentPosition.TradeType == TradeType.Buy)
            {
                if (currentSymbol.Bid > this.currentPosition.TakeProfit - (this.currentSymbol.PipSize * this.TriggerPips))
                    return true;

            }
            else
            {
                if (currentSymbol.Ask < this.currentPosition.TakeProfit + (this.currentSymbol.PipSize * this.TriggerPips))
                    return true;
            }

            return false;
        }


    }
}

 

I think combining these three features with the right parimeters would work wonders. Any thoughts or suggestions will be appreciated :) 

 


@theonlinemick