martingale with SL and MM free

by aysos75 in category Range at 18/06/2015
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

 

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
#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;
        }

    }
}
Comments

aysos75 - June 20, 2015 @ 21:45

the project is under github and the stats is here

aysos75 - June 21, 2015 @ 13:41

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.

 

aysos75 - June 21, 2015 @ 13:42

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.

hichem - June 22, 2015 @ 12:54

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.

tradermatrix - June 22, 2015 @ 21:38

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

 

noniz - June 22, 2015 @ 22:24

salut cher monsieur
i ai testé votre robot, il est pas ce robot réel qui est téléchargé à ctdn.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

aysos75 - June 23, 2015 @ 00:47

the new copy trading reference is

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

aysos75 - June 23, 2015 @ 00:52

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

aysos75 - June 23, 2015 @ 01:00

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

 

Luckyman86 - June 23, 2015 @ 13:55

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

 

aysos75 - June 24, 2015 @ 21:00

yes I have updated it

aysos75 - June 27, 2015 @ 09:07

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.

aysos75 - June 27, 2015 @ 10:34

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

 

 

8081871 - June 28, 2015 @ 19:19

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

 

JasperForex - June 28, 2015 @ 22:30

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

Keep up the great work!

JasperForex - June 28, 2015 @ 22:32

nevermind - found it as mforex on cmirror.

aysos75 - June 29, 2015 @ 20:27

@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

 

hmeshtawy - July 16, 2015 @ 01:21

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 ?

aysos75 - July 17, 2015 @ 15:19

You can find Candlestick Tendency II here :

link to Candlestick Tendency II

Read the information about installation here

 

aysos75 - July 17, 2015 @ 15:21

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

aysos75 - July 17, 2015 @ 15:24

the new link to myfxbook statistique about martingale forex 1.7.0.0

is here

aysos75 - July 17, 2015 @ 15:26

sorry for the two precedents mistakes

 

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

Davidunx - August 24, 2015 @ 22:42

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

aysos75 - September 11, 2015 @ 14:36

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

kaarel tamm - September 22, 2015 @ 13:00

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

conny.rosenberg@gmail.com - October 04, 2015 @ 16:15

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

Robot forex - December 08, 2015 @ 11:59

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

Harold_182236 - November 17, 2016 @ 16:04

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

mrsully80 - July 17, 2017 @ 23:04

@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!

boyrayza - August 08, 2018 @ 10:37

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?

5