Category Range  Published on 10/07/2015

martingale with SL and MM

Description

This robot is a fork of Robot_Forex. It is hosted on Github and gives good results. If you want to have the last evolutions of the bot, take it here

It manages a stop loss, a money management , a tralling stop and dynamic grid to her positions.

For the parameters to use go to Github

A video a.bout this bot is on youtube

Résultat du backtest version 1.4.5.0 EURUSD minute4

Gains et pertes du 22 juin 2015

 


#region Licence
//The MIT License (MIT)
//Copyright (c) 2014 abdallah HACID, https://www.facebook.com/ab.hacid

//Permission is hereby granted, free of charge, to any person obtaining a copy of this software
//and associated documentation files (the "Software"), to deal in the Software without restriction,
//including without limitation the rights to use, copy, modify, merge, publish, distribute,
//sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
//is furnished to do so, subject to the following conditions:

//The above copyright notice and this permission notice shall be included in all copies or
//substantial portions of the Software.

//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
//BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
//DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// Project Hosting for Open Source Software on Github : https://github.com/abhacid/Robot_Forex
#endregion


#region Description
//
// Le projet et sa description se trouvent sur Github à l'adresse https://github.com/abhacid/Martingale_Forex
//
// Ce projet permet d'écrire un robot de trading basé sur un exemple Robot_Forex initial écrit par 
// imWald sur le dépôt de code source CTDN.
//
// Pour résumer c'est une martingale avec stop loss et money management.

#endregion

using System;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.Lib;

namespace cAlgo.Robots
{
    [Robot("Martingale Forex", AccessRights = AccessRights.None)]
    public class Martingale_Forex : Robot
    {
        #region Parameters
        [Parameter("Money Management (%)", DefaultValue = 1.6, MinValue = 0)]
        public double MoneyManagement { get; set; }

        [Parameter("Take Profit", DefaultValue = 5, MinValue = 5)]
        public double TakeProfit { get; set; }

        [Parameter("Stop Loss Factor", DefaultValue = 5.5, MinValue = 0.1)]
        public double StopLossFactor { get; set; }

        [Parameter("Martingale", DefaultValue = 0.5, MinValue = 0)]
        public double MartingaleCoeff { get; set; }

        [Parameter("Max Orders", DefaultValue = 2, MinValue = 2)]
        public int MaxOrders { get; set; }

        #endregion

        private bool isRobotStopped;
        private string botName;
        // le label permet de s'y retrouver parmis toutes les instances possibles.
        private string instanceLabel;

        private double stopLoss;
        private double firstLot;
        private StaticPosition corner_position;
        private string BotVersion = "1.3.2.0";
        private bool DEBUG;


        protected override void OnStart()
        {
            DEBUG = true;
            botName = ToString();
            instanceLabel = botName + "-" + BotVersion + "-" + Symbol.Code + "-" + TimeFrame.ToString();

            stopLoss = TakeProfit * StopLossFactor;
            Positions.Opened += OnPositionOpened;

            int corner = 1;

            switch (corner)
            {
                case 1:
                    corner_position = StaticPosition.TopLeft;
                    break;
                case 2:
                    corner_position = StaticPosition.TopRight;
                    break;
                case 3:
                    corner_position = StaticPosition.BottomLeft;
                    break;
                case 4:
                    corner_position = StaticPosition.BottomRight;
                    break;
            }

            if (!DEBUG)
                ChartObjects.DrawText("BotVersion", botName + " Version : " + BotVersion, corner_position);


            Print("The current symbol has PipSize of: {0}", Symbol.PipSize);
            Print("The current symbol has PipValue of: {0}", Symbol.PipValue);
            Print("The current symbol has TickSize: {0}", Symbol.TickSize);
            Print("The current symbol has TickSValue: {0}", Symbol.TickValue);
        }

        protected override void OnTick()
        {
            if (Trade.IsExecuting)
                return;

            Position[] positions = GetPositions();

            if (positions.Length > 0 && isRobotStopped)
                return;
            else
                isRobotStopped = false;

            if (positions.Length == 0)
            {
                // Calcule le volume en fonction du money management pour un risque maximum et un stop loss donné.
                // Ne tient pas compte des risques sur d'autres positions ouvertes du compte de trading utilisé
                double maxVolume = this.moneyManagement(MoneyManagement, stopLoss);
                firstLot = maxVolume / (MaxOrders + (MartingaleCoeff * MaxOrders * (MaxOrders - 1)) / 2.0);

                if (firstLot <= 0)
                    throw new System.ArgumentException(String.Format("the 'first lot' : {0} parameter must be positive and not null", firstLot));
                else
                    SendFirstOrder(firstLot);
            }
            else

                ControlSeries();
        }

        protected override void OnError(Error CodeOfError)
        {
            if (CodeOfError.Code == ErrorCode.NoMoney)
            {
                isRobotStopped = true;
                Print("ERROR!!! No money for order open, robot is stopped!");
            }
            else if (CodeOfError.Code == ErrorCode.BadVolume)
            {
                isRobotStopped = true;
                Print("ERROR!!! Bad volume for order open, robot is stopped!");
            }
        }

        private void OnPositionOpened(PositionOpenedEventArgs args)
        {
            double? stopLossPrice = null;
            double? takeProfitPrice = null;

            switch (GetPositionsSide())
            {
                case 0:
                    double averageBuyPrice = GetAveragePrice(TradeType.Buy);
                    takeProfitPrice = averageBuyPrice + TakeProfit * Symbol.PipSize;
                    stopLossPrice = averageBuyPrice - stopLoss * Symbol.PipSize;
                    break;
                case 1:
                    double averageSellPrice = GetAveragePrice(TradeType.Sell);
                    takeProfitPrice = averageSellPrice - TakeProfit * Symbol.PipSize;
                    stopLossPrice = averageSellPrice + stopLoss * Symbol.PipSize;
                    break;
            }

            if (stopLossPrice.HasValue || takeProfitPrice.HasValue)
            {
                Position[] positions = GetPositions();

                foreach (Position position in positions)
                {
                    if (stopLossPrice != position.StopLoss || takeProfitPrice != position.TakeProfit)
                        ModifyPosition(position, stopLossPrice, takeProfitPrice);
                }
            }
        }

        private void SendFirstOrder(double OrderVolume)
        {
            switch (GetSignal())
            {
                case 0:
                    executeOrder(TradeType.Buy, OrderVolume);
                    break;
                case 1:
                    executeOrder(TradeType.Sell, OrderVolume);
                    break;
            }
        }

        private void ControlSeries()
        {
            Position[] positions = GetPositions();

            if (positions.Length < MaxOrders)
            {
                long volume = Symbol.NormalizeVolume(firstLot * (1 + MartingaleCoeff * positions.Length), RoundingMode.ToNearest);
                int countOfBars = (int)(25.0 / positions.Length);

                int pipstep = GetDynamicPipstep(countOfBars, MaxOrders - 1);
                int positionSide = GetPositionsSide();

                switch (positionSide)
                {
                    case 0:
                        double lastBuyPrice = GetLastPrice(TradeType.Buy);

                        if (!DEBUG)
                            ChartObjects.DrawHorizontalLine("gridBuyLine", lastBuyPrice - pipstep * Symbol.PipSize, Colors.Green, 2);

                        if (Symbol.Ask < lastBuyPrice - pipstep * Symbol.PipSize)
                            executeOrder(TradeType.Buy, volume);
                        break;

                    case 1:
                        double lastSellPrice = GetLastPrice(TradeType.Sell);

                        if (!DEBUG)
                            ChartObjects.DrawHorizontalLine("gridSellLine", lastSellPrice + pipstep * Symbol.PipSize, Colors.Red, 2);

                        if (Symbol.Bid > lastSellPrice + pipstep * Symbol.PipSize)
                            executeOrder(TradeType.Sell, volume);
                        break;
                }
            }

            if (!DEBUG)
                ChartObjects.DrawText("MaxDrawdown", "MaxDrawdown: " + Math.Round(GetMaxDrawdown(), 2) + " Percent", corner_position);
        }

        // You can modify the condition of entry here.
        private int GetSignal()
        {
            int Result = -1;
            int LastBarIndex = MarketSeries.Close.Count - 2;
            int PrevBarIndex = LastBarIndex - 1;

            // two up candles for a buy signal.
            if (MarketSeries.Close[LastBarIndex] > MarketSeries.Open[LastBarIndex])
                if (MarketSeries.Close[PrevBarIndex] > MarketSeries.Open[PrevBarIndex])
                    Result = 0;

            // two down candles for a sell signal.
            if (MarketSeries.Close[LastBarIndex] < MarketSeries.Open[LastBarIndex])
                if (MarketSeries.Close[PrevBarIndex] < MarketSeries.Open[PrevBarIndex])
                    Result = 1;

            return Result;
        }

        private TradeResult executeOrder(TradeType tradeType, double volume)
        {
            //Print("normalized volume : {0}", Symbol.NormalizeVolume(volume, RoundingMode.ToNearest));
            return ExecuteMarketOrder(tradeType, Symbol, Symbol.NormalizeVolume(volume, RoundingMode.ToNearest), instanceLabel);
        }

        private Position[] GetPositions()
        {
            return Positions.FindAll(instanceLabel, Symbol);
        }

        private double GetAveragePrice(TradeType TypeOfTrade)
        {
            double Result = Symbol.Bid;
            double AveragePrice = 0;
            long count = 0;

            foreach (Position position in GetPositions())
            {
                if (position.TradeType == TypeOfTrade)
                {
                    AveragePrice += position.EntryPrice * position.Volume;
                    count += position.Volume;
                }
            }

            if (AveragePrice > 0 && count > 0)
                Result = AveragePrice / count;

            return Result;
        }

        private int GetPositionsSide()
        {
            int Result = -1;
            int BuySide = 0, SellSide = 0;
            Position[] positions = GetPositions();

            foreach (Position position in positions)
            {
                if (position.TradeType == TradeType.Buy)
                    BuySide++;

                if (position.TradeType == TradeType.Sell)
                    SellSide++;
            }

            if (BuySide == positions.Length)
                Result = 0;

            if (SellSide == positions.Length)
                Result = 1;

            return Result;
        }

        private int GetDynamicPipstep(int CountOfBars, int division)
        {
            int Result;
            double HighestPrice = 0, LowestPrice = 0;
            int StartBar = MarketSeries.Close.Count - 2 - CountOfBars;
            int EndBar = MarketSeries.Close.Count - 2;

            for (int i = StartBar; i < EndBar; i++)
            {
                if (HighestPrice == 0 && LowestPrice == 0)
                {
                    HighestPrice = MarketSeries.High[i];
                    LowestPrice = MarketSeries.Low[i];
                    continue;
                }

                if (MarketSeries.High[i] > HighestPrice)
                    HighestPrice = MarketSeries.High[i];

                if (MarketSeries.Low[i] < LowestPrice)
                    LowestPrice = MarketSeries.Low[i];
            }

            Result = (int)((HighestPrice - LowestPrice) / Symbol.PipSize / division);

            return Result;
        }

        private double savedMaxBalance;
        private List<double> drawdown = new List<double>();
        private double GetMaxDrawdown()
        {
            savedMaxBalance = Math.Max(savedMaxBalance, Account.Balance);

            drawdown.Add((savedMaxBalance - Account.Balance) / savedMaxBalance * 100);
            drawdown.Sort();

            double maxDrawdown = drawdown[drawdown.Count - 1];

            return maxDrawdown;
        }

        private double GetLastPrice(TradeType tradeType)
        {
            double LastPrice = 0;

            foreach (Position position in GetPositions())
            {
                if (tradeType == TradeType.Buy)
                    if (position.TradeType == tradeType)
                    {
                        if (LastPrice == 0)
                        {
                            LastPrice = position.EntryPrice;
                            continue;
                        }
                        if (position.EntryPrice < LastPrice)
                            LastPrice = position.EntryPrice;
                    }

                if (tradeType == TradeType.Sell)
                    if (position.TradeType == tradeType)
                    {
                        if (LastPrice == 0)
                        {
                            LastPrice = position.EntryPrice;
                            continue;
                        }
                        if (position.EntryPrice > LastPrice)
                            LastPrice = position.EntryPrice;
                    }
            }

            return LastPrice;
        }

    }
}


AY
aysos75

Joined on 28.09.2013

  • Distribution: Free
  • Language: C#
  • Trading platform: cTrader Automate
  • File name: Martingale_Forex.algo
  • Rating: 1.67
  • Installs: 8870
  • Modified: 13/10/2021 09:54
Comments
Log in to add a comment.
BO
boyrayza · 6 years ago

Hi 

Now it Errer 1

Error CS0234: The type or namespace name 'Lib' does not exist in the namespace 'cAlgo' (are you missing an assembly reference?)

Who can help me?

MR
mrsully80 · 7 years ago

@aysos75 Nice job. After early optimization and backtesting results show some promise. The only thing I would ask is if you could add an initial volume parameter with min/max values from 0.01 - 1

thank you and keep up the good work!

HA
Harold_182236 · 7 years ago

Hello

Your "Martigale_Forex" strategy is pretty sound. However, I am getting two errors when I tried to compile it. They are:

1. Error CS0246: The type or namespace name 'GlobalAverageTrueRange' could not be found (are you missing a using directive or an assembly reference?)

2. Error CS0246: The type or namespace name 'DirectionalMovementSystemRating' could not be found (are you missing a using directive or an assembly reference?)

I am pretty new at programming with C Sharp, so my Learning Curve is very daunting.

Can you please help me with the solution to these errors. I did some French in High School, but never paid sufficient attention, I am now finding out most painfully.

Thanks

Harold

RO
Robot forex · 8 years ago

aysos75, thank you,

I appreciate your help with this both. Could you please make available for everyone the latest version? We find difficulty to decompile as windows OS users.

Best

CO
conny.rosenberg@gmail.com · 9 years ago

hello

 

Can somebody explain how to do , get little error when try from github, i dont know if i do it right.

Some for dummies :) have little know how with compile :/

conny

KA
kaarel tamm · 9 years ago

Looks good but also cant get it work because of the Lib error. I tried to find solution from Github but french makes it very difficult to understand the instructions.

Have used your other projects and have got decent result. Thanks aysos75

AY
aysos75 · 9 years ago

If you want to compile the bot, you have to download the source on github and to read the explanations on https://github.com/abhacid/Martingale_Forex

DA
Davidunx · 9 years ago

The compiler points a Lib error, what is the problem?

AY
aysos75 · 9 years ago

sorry for the two precedents mistakes

 

link to myfxbook : http://www.myfxbook.com/members/abhacid/mforex-1700/1304163

AY
aysos75 · 9 years ago

the new link to myfxbook statistique about martingale forex 1.7.0.0

is here

AY
aysos75 · 9 years ago

the new link to myfxbook statistique about martingale forex 1.7.0.0 is here

AY
aysos75 · 9 years ago

You can find Candlestick Tendency II here :

link to Candlestick Tendency II

Read the information about installation here

 

HM
hmeshtawy · 9 years ago

Error CS0246: The type or namespace name 'CandlestickTendencyII' could not be found (are you missing a using directive or an assembly reference?)

 

where can I find CandlestickTendencyII Indicator ?

AY
aysos75 · 9 years ago

@8081871

Hello,

To compile the program must retrieve the bookstore on github and also the latest Martingale_Forex.

I made a Video explains how.

You can view the result in myfxbook, or in cMirror

Best Regards

 

JasperForex's avatar
JasperForex · 9 years ago

nevermind - found it as mforex on cmirror.

JasperForex's avatar
JasperForex · 9 years ago

the cMirror instance is also missing all of a sudden...

Keep up the great work!

80
8081871 · 9 years ago

Hi Aysos,

First of all, thank you for sharing the robot with us. Does anyone know how to solve this problem, it is probably a basic one. Here, the algo doesn't build, instead it shows this message:

Error : Project C:\Users\Nikolas\Documents\cAlgoBots\Sources\Library\cAlgoLib\cAlgo.Lib.csproj doesn't exist.

Regards

 

AY
aysos75 · 9 years ago

the first link don't work clic on the second link

 

 

AY
aysos75 · 9 years ago

I made a Youtube video in french to explain how to get the Visual Studio solution from Github and how to edit and debug the robot in conjunction with cAlgo.

J'ai fait une vidéo Youtube en français pour expliquer comment récupérer la solution Visual studio à partir de Github et comment modifier et déboguer le robot en liaison avec cAlgo.

AY
aysos75 · 9 years ago

yes I have updated it

LU
Luckyman86 · 9 years ago

Download link is not working is not working here on CTDN - you may want top update this for the new version you have released

 

AY
aysos75 · 9 years ago

By the weekend I would make an instructional video to make everything work between cTDN, Github and visual studio.

Basically everything is explained on github with settings files and screenshots in a specific folder of the Visual Studio solution. The robot runs on cMiror and can be replicated on one of your demo accounts

 

AY
aysos75 · 9 years ago

@hichem

Yes the screenshot refers to an early version since evolved program. for the latest version must be recovered on github.
It is in the 1.3.3.1 release.

AY
aysos75 · 9 years ago

the new copy trading reference is

https://cm.spotware.com/strategy/56298

NO
noniz · 9 years ago

salut cher monsieur
i ai testé votre robot, il est pas ce robot réel qui est téléchargé à ctrader.com
selon de mettre les fichiers à la version de robot GitHub est différente, s'il vous plaît télécharger le fichier de code réelle ou écrire la méthode comment le faire travailler, qui est disponible à github.
je suis face à trop de problèmes. aider s'il vous plaît.

Merci et salutations

TR
tradermatrix · 9 years ago

cher  Abdalah Hacid

Merci pour cette idée et de la partager avec tous....

J ai  progressé en regardant vos codes et vos méthodes.

Je suis ok avec Hichem,j ai actuellement le même soucis avec backesting tick data....

Il y a un problème.../forum/calgo-support/5418

Cordialement

 

Bons Trades

 

HI
hichem · 9 years ago

Hello and thank you for the algo

The screenshot doesn't reflect reality:

The Max Risk (%) paraemter is set to be of type int, whereas in the screenshot it has a value of double.

The backtest curve is not the curve realized when using the Robot on the paraemters shown on the screenshot.

AY
aysos75 · 9 years ago

I put on Martingale_Forex on CMiror:

https://cm.spotware.com/strategy/56296

it copies the positions he takes on either a demo account is a real account.

AY
aysos75 · 9 years ago

I put on Martingale_Forex on CMiror:

https://cm.spotware.com/strategy/56296

it copies the positions he takes on either a demo account is a real account.

 

AY
aysos75 · 9 years ago

the project is under github and the stats is here