Ciao, la strategia “Dynamic Range Revert – Scalping” è una strategia molto semplice, utilizzata da molte persone, anche dai trader retail… ma noi non abbiamo tempo da perdere, noi vogliamo tutto automatico!

Ciao, sono Drilon e sono un programmatore con la passione per la finanza personale, mi piace scrivere strategie automatiche e vedere che risultati portano. Questa strategia è l’inversa di un’altra strategia che ho scritto in precedenza (https://www.investoinvestigando.it/dynamic-breakout-scalping/).

Idea

L’idea di base è molto semplice, c’è un range di tempo in cui viene definito un range di prezzo, ovvero un massimo e un minimo. Dopodiché abbiamo un altro range di tempo nel quale si attende la rottura del range di prezzo in uno dei due lati.

Una volta subita la rottura apriamo un ordine al contrario, ovvero se abbiamo il punto di rottura nel prezzo MIN, apriamo un ordine in BUY e viceversa. Quindi l’idea è quella di trovare dei falsi breakout.

Ok, adesso sappiamo quando entrare, ma quando è il momento di uscire? L’idea è quella di dare “respiro/tempo” al mercato di andare a raggiungere il nostro target. Il target è di circa 10 pips poiché, statisticamente, abbiamo il 98% di probabilità di arrivare a target! Quindi non c’è un vero stop loss ma c’è un altro momento in cui usciamo dal trade, non possiamo mica stare a mercato per sempre…

Il secondo modo di uscita è dato da un orario nel quale il mercato inizia a calmarsi e non c’è molto movimento, quindi che si sia in profitto o in perdita, si chiude e andiamo al giorno dopo! Nessuna strategia di trading è perfetta al 100%, ma….

Risultati

Backtest

Come puoi vedere, in 11 anni la strategia rende molto bene! Non farti fregare dal numero grosso di 71k di profitto e del 718% di profitto, perché quello dipende da quanto budget uno ha, sono ordini fatti con 1 lotto (non alla portata di tutti). Da questa figura ci interessa sapere solo l’andamento, vedere se è costante oppure no. Basta! Ora andiamo nel dettaglio

Vediamo che ci sono stati 2534 ordini di cui 2115 in profitto quindi abbiamo un 83% di win rate (probabilità di vincere un trade). Andiamo a vedere le note dolenti!

Abbiamo un Drawdown del 62% che è tantissimo…molti trader quando vai al 50% ti chiudono l’operazioni in automatico. Poi abbiamo che il peggior trader ha fatto perdere 1348€ e qui la domanda che ci dobbiamo fare è “Ho abbastanza budget da sopportare una perdita del genere? Mentalmente come mi farebbe sentire una perdita del genere?”

Vediamo che ci sono stati massimo 3 ordini consecutivi andati in negativo, perchè è importante questo dato? Sempre a livello mentale, perchè magari ci sono persone che preferiscono guadagnare poco ma guadagnare spesso, invece ci sono altre persone che riescono a sopportare più perdite consecutive per poi fare dei grossi guadagni! Questo dipende tutto da come siamo fatti mentalmente.

Personalmente preferisco rischiare di meno ma avere un guadagno costante. Quindi cosa faccio? Invece di puntare 1 lotto ad ogni trade, vado a diminuire!

Immagina puntando 0.1 lotti, guadagno totale in 11 anni è di circa 7,1k, quindi è molto inferiore, però quanto rischiamo? Il drawdown scende al 6,2% (niente male eh) ed il peggior trade mi fa perdere 134,8€. Diventa tutto più accettabile giusto? Se è ancora troppo, diminuisci i lotti fino a quando non sei confidente e a tuo agio con la strategia, l’importante è che nel tempo siamo in profitto

Si lo so vuoi il codice e vuoi provare da solo, ecco qui:

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(AccessRights = AccessRights.None)]
    public class IIDynamicRangeBreakoutREVERT : Robot
    {
        [Parameter(DefaultValue = 10)]
        public double takeProfit { get; set; }

        [Parameter(DefaultValue = 10)]
        public double stopLoss { get; set; }

        [Parameter(DefaultValue = 8)]
        public int hourEnter { get; set; }

        [Parameter(DefaultValue = 18)]
        public int hourExit { get; set; }
        
        [Parameter(DefaultValue = 8)]
        public int hourClosingOpen{ get; set; }

        [Parameter(DefaultValue = 18)]
        public int hourClosingExit { get; set; }
        
        [Parameter(DefaultValue = 1)]
        public int maxOrder { get; set; }
        
        [Parameter(DefaultValue = 0)]
        public double maxRange { get; set; }
        
        [Parameter(DefaultValue = 999999)]
        public double minRange { get; set; }
        
        [Parameter(DefaultValue = 0.01)]
        public double lots { get; set; }
        

        protected override void OnTick()
        {
            // Handle price updates here
            if(!checkTime()){
                // Break Range
                if(Bars.LastBar.Close > maxRange && maxRange != 0){
                    // Open BUY
                    Open(TradeType.Sell, lots);
                    maxRange = 0;
                    minRange = 999999;
                }  
                
                if(Bars.LastBar.Close < minRange && minRange != 999999){
                    // Open SELL
                    Open(TradeType.Buy, lots);
                    maxRange = 0;
                    minRange = 999999;
                }
            }
            
            if(checkClosingTime()){
                CloseAll();
            }
        }
        
        protected override void OnBar()
        {
        
            if(checkTime()){
                Print("DENTRO");
                // Set Range
                if(Bars.LastBar.High > maxRange ){
                    maxRange = Bars.LastBar.High;
                }  
                
                if(Bars.LastBar.Low < minRange ){
                    minRange = Bars.LastBar.Low;
                }
            }    
        }

        protected override void OnStop()
        {
            CloseAll();
        }
        
        private bool checkTime()
        {
            DateTime date = Server.Time;
            if (date.Hour >= hourEnter && date.Hour <= hourExit && hourEnter <= hourExit && hourClosingOpen > hourExit)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        
        private bool checkClosingTime()
        {
            DateTime date = Server.Time;
            if (date.Hour >= hourClosingOpen && date.Hour <= hourClosingExit && hourClosingOpen <= hourClosingExit)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        
        private void CloseAll()
        {
            foreach (var position in Positions)
            {
                ClosePosition(position);
            }
        }
        
        private void Close(TradeType tradeType)
        {
            foreach (var position in Positions.FindAll("Order", SymbolName, tradeType))
                ClosePosition(position);
        }

        private void Open(TradeType tradeType, double lots)
        {
            var position = Positions.FindAll("Order", SymbolName, tradeType);
            var volumeInUnits = Symbol.QuantityToVolumeInUnits(lots);
            if (position == null || position.Length < maxOrder)
                ExecuteMarketOrder(tradeType, SymbolName, volumeInUnits, "Order", stopLoss, takeProfit);
        }
    }
}

PARAMETRI:

Timeframe e valuta: EURUSD – 1m

takeProfit: 20

stopLoss: 90

hourEnter: 14

hourExit: 15

hourClosingOpen: 23

hourClosingExit: 15

maxOrder:1

maxRange: 0

minRange: 99999999

lots: a piacimento

Se vuoi vedere delle strategie da utilizzare inizia da qui: https://www.investoinvestigando.it/una-strategia-per-sempre-algotrading/

Se hai dubbi o domande fammele pure su Telegram: https://t.me/+0xQYD3WKIAA5Mjg8

Seguimi su instagram: https://www.instagram.com/investoinvestigando.it/