Adding a new feature to my cBot

Created at 23 Mar 2019
PA

paindoo.marketing

Joined 23.03.2019

Status

Open


Budget

50.00 USD


Payment Method

Direct Payment

Job Description

Hi there,

I need some additional features for my cBot.

There is not need to change or amend any existing features, need to add the following feature to it. cTrader recently allowed use of ModifyPosition[Async] feature to add volume to existing positions, before you could not do it using cBot but manually. 

When a position is Profitable/Loss by "X" number of pips it should add volume to the position. In other words the position doubles its volume size. 

Parameters required:

Doubling Profitable Position: Yes/NO
Doubling Profitable Pips: XXX

Doubling Losing Position: Yes/NO
Doubling Losing Pips: XXX

This feature should add volume to the current position using ModifyPosition[Async], it should work both ways for Profitable Positions and Losing Positions. But both should be able to work 
separately, for example if you only want to double a profitable position then you 
should be able to disable the losing position feature.

The Doubling Profitable Position is enabled and the Doubling Pips is “10” now the 
position is at 100 and once the price reaches 110 then the position should double and 
once it doubled, the position comes to 105. It should double every time it meets the 
criteria, meaning if the price keeps going up so every 10 pips it should double.

It should do the same for losing positions.

If you need anymore information about it please write back to me.

Here is a link to dowload the cBot

https://drive.google.com/open?id=0B9-f8sILjcPfSUR5UGxjQ2ZCaGM

Kindest regards,

Sohail

sohail.abbas@live.co.uk   Please use cBot in subject line

 

//+------------------------------------------------------------------+
//|                                                  Prince Bobby    |
//|                                            Copyright 2015, PB    |
//|                                       sohail.abbas@live.co.uk    |
//+------------------------------------------------------------------+
//-Prince Bobby cBot based on Bar-Time & Trend. For range market & 15 
//minute TimeFrame is best.

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Version  Date            Changes                                                                         //
// 2.00     03-Apr-2016     1) Orders after the initial position have been changed from MARKET to STOP      //
//                          orders. 2) Added parameter StopOrderDistance which specifies distance at which  //
//                          STOP orders are placed. 3) Added parameter OneTradePerCandle which specifies    //
//                          whether to open only one POSITION (or ORDER) of the same type per candle.       //
//                          4) Added detailed logging to Log of POSITION opened, closed and ORDER placed.   //
// 2.01     12-Apr-2016     1) Bug-fixes for BUY-STOP orders.                                               //
// 2.02     15-Apr-2016     1) Accurate currency displayed in panel (e.g. $, £ etc).                        //
// 2.03     05-Oct-2016     1) Initial SL and Trailing SL features added.                                   //
// 2.04     06-Oct-2016     1) Rework of v2.03. Initial SL and Trailing SL renamed TS Trigger and TS        //
//                          Distance respectively.                                                          // 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

using System;
using cAlgo.API;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SuperBOT : Robot
    {
        [Parameter("Buy", DefaultValue = true)]
        public bool Buy { get; set; }

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

        [Parameter("Pip Step", DefaultValue = 5, MinValue = 1)]
        public int PipStep { get; set; }

        [Parameter("Stop Order Distance (pips)", DefaultValue = 5, MinValue = 1)]
        public int StopOrderDistance { get; set; }

        [Parameter("First Volume", DefaultValue = 5000, MinValue = 1000, Step = 1000)]
        public int FirstVolume { get; set; }

        [Parameter("Volume Exponent", DefaultValue = 1.0, MinValue = 0.1, MaxValue = 5.0)]
        public double VolumeExponent { get; set; }

        [Parameter("Max Spread", DefaultValue = 3.0)]
        public double MaxSpread { get; set; }

        [Parameter("Average TP", DefaultValue = 25, MinValue = 1)]
        public int AverageTP { get; set; }

        [Parameter("One Trade per Candle", DefaultValue = false)]
        public bool OneTradePerCandle { get; set; }

        [Parameter("Trailing Stop Enabled", DefaultValue = true)]
        public bool TS_Enabled { get; set; }

        [Parameter("Trailing Stop Trigger (pips)", DefaultValue = 5, MinValue = 0)]
        public int TS_Trigger { get; set; }

        [Parameter("Trailing Stop Distance (pips)", DefaultValue = 1, MinValue = 0)]
        public int TS_Distance { get; set; }

        private const string LABEL = "cls";
        private double currentSpread;
        private bool cStop = false;
        private string FORMAT_PRICE = "N5";
        private int m_PendingCount = -1;
        private int m_OpenCount = -1;
        private string m_Currency = "$";
        private int m_TsPips = 0;

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // PositionInfo
        // Class that stores summary information of TradeType. 
        // E.g. summary of BUY positions and summary of SELL positions
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        class PositionSummary
        {
            public uint Count = 0;
            // Total number of open positions.
            public uint PendingCount = 0;
            // Total number of pending orders.
            public double AveragePrice = 0;
            // Average price of open positions.
            public double HighestPrice = double.MinValue;
            // Highest price of open position or pending order.
            public double LowestPrice = double.MaxValue;
            // Lowest price of open position or pending order.
            public long Volume = 0;
            // Total volume of the open positions.
            public double CumulativeValue = 0.0;
            // Cumulative value (price x volume) of open positions.
            public double TargetPrice = 0.0;
            // Target price
            public DateTime LastTradeTime = new DateTime(1970, 1, 1);
            // The (candle) time of the last opened position or order.
            public double Commission = 0.0;
            // Commission
            public long LastVolume = 0;
            // Volume of the latest position / order
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // Reset
            // Clear / reset the PositionSummary values
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            public void Reset()
            {
                Count = 0;
                Commission = 0.0;
                PendingCount = 0;
                AveragePrice = 0.0;
                HighestPrice = double.MinValue;
                LowestPrice = double.MaxValue;
                LastVolume = 0;
                Volume = 0;
                CumulativeValue = 0.0;
                TargetPrice = 0.0;
            }
        }

        PositionSummary m_buyTrades = new PositionSummary();
        // Summary of BUY positions and BUY-STOP orders.
        PositionSummary m_sellTrades = new PositionSummary();
        // Summary of SELL positions and SELL-STOP orders.
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // OnStart
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        protected override void OnStart()
        {
            if (TS_Enabled)
            {
                m_TsPips = TS_Trigger + TS_Distance;
                if (TS_Distance <= 0)
                {
                    TS_Enabled = false;
                    Print("ERROR : Trailing Stop Distance (pips) should be greater than zero. cBot STOPPED.");
                    this.Stop();
                    return;
                }

            }
            FORMAT_PRICE = string.Format("N{0}", Symbol.Digits);
            if (Account.Currency == "AUD")
                m_Currency = "$";
            else if (Account.Currency == "EUR")
                m_Currency = "€";
            else if (Account.Currency == "GBP")
                m_Currency = "£";
            else if (Account.Currency == "INR")
                m_Currency = "₹";
            else if (Account.Currency == "JPY")
                m_Currency = "¥";
            else if (Account.Currency == "USD")
                m_Currency = "$";
            else
                m_Currency = Account.Currency;

            Positions.Closed += PositionsOnClosed;
            Positions.Opened += PositionsOnOpened;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // OnStop
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        protected override void OnStop()
        {
            ChartObjects.RemoveAllObjects();
            Positions.Closed -= PositionsOnClosed;
            Positions.Opened -= PositionsOnOpened;
            m_buyTrades = null;
            m_sellTrades = null;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // PositionsOnClosed
        // Event when position is closed
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        private void PositionsOnClosed(PositionClosedEventArgs args)
        {
            var position = args.Position;
            if (position.SymbolCode == Symbol.Code)
            {
                if (position.Label == LABEL)
                    Print("{0} Position #{1} closed at P/L of {2} pips.", (position.TradeType == TradeType.Buy ? "BUY" : "SELL"), position.Id, position.Pips.ToString("N1"));
            }
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // PositionsOnOpened
        // Even received when position is opened
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        private void PositionsOnOpened(PositionOpenedEventArgs args)
        {
            var position = args.Position;
            if (position.SymbolCode == Symbol.Code)
            {
                if (position.Label == LABEL)
                {
                    if ((m_buyTrades.Count == 0) && (position.TradeType == TradeType.Buy))
                        return;
                    if ((m_sellTrades.Count == 0) && (position.TradeType == TradeType.Sell))
                        return;

                    Print("{0} Position #{1} opened at {2}.", (position.TradeType == TradeType.Buy ? "BUY" : "SELL"), position.Id, position.EntryPrice.ToString(FORMAT_PRICE));
                }
            }
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // OnTick
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        protected override void OnTick()
        {
            try
            {
                currentSpread = (Symbol.Ask - Symbol.Bid) / Symbol.PipSize;
                evaluatePositions();
                if ((m_PendingCount != PendingOrders.Count) || (m_OpenCount != Positions.Count))
                {
                    m_PendingCount = PendingOrders.Count;
                    m_OpenCount = Positions.Count;

                    if (m_buyTrades.Count > 0)
                        updateTakeProfit(TradeType.Buy, m_buyTrades.AveragePrice + AverageTP * Symbol.PipSize);

                    if (m_sellTrades.Count > 0)
                        updateTakeProfit(TradeType.Sell, m_sellTrades.AveragePrice - AverageTP * Symbol.PipSize);
                }
                if ((currentSpread <= MaxSpread) && !cStop)
                {
                    if ((m_buyTrades.Count == 0) || (m_sellTrades.Count == 0))
                        placeInitialGridOrders();
                    if ((m_buyTrades.Count > 0) || (m_sellTrades.Count > 0))
                        runGrid();
                }
                if (TS_Enabled)
                    evaluateStops();
                drawGraphics();
            } catch (Exception ex)
            {
                Exception inEx = ex;
                while (inEx != null)
                {
                    Print("ERROR : OnTick. {0} at {1}.", ex.Message, ex.StackTrace);
                    inEx = ex.InnerException;
                }
            }
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // OnError
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        protected override void OnError(Error error)
        {
            if (error.Code == ErrorCode.NoMoney)
            {
                cStop = true;
                Print("ERROR : NOT ENOUGH MONEY. cBot STOPPED");
                try
                {
                    deletePendingStopOrders(TradeType.Buy);
                    deletePendingStopOrders(TradeType.Sell);
                } catch (Exception ex)
                {
                    Exception inEx = ex;
                    while (inEx != null)
                    {
                        Print("ERROR : OnError. {0} at {1}.", ex.Message, ex.StackTrace);
                        inEx = ex.InnerException;
                    }
                } finally
                {
                    this.Stop();
                }
            }
            else
            {
                Print("ERROR : OnError Code {0}.", error.Code.ToString());
            }
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // OnBar
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        protected override void OnBar()
        {
            RefreshData();
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // evaluatePositions
        // Evaluate all open positions and pending orders, and calculate summary information
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        private void evaluatePositions()
        {
            m_buyTrades.Reset();
            m_buyTrades.LastVolume = FirstVolume;
            m_sellTrades.Reset();
            m_sellTrades.LastVolume = FirstVolume;
            for (int i = 0; i < Positions.Count; i++)
            {
                Position thisPos = Positions[i];
                if (thisPos.SymbolCode != Symbol.Code)
                    continue;
                if (thisPos.Label != LABEL)
                    continue;
                if (thisPos.TradeType == TradeType.Buy)
                {
                    m_buyTrades.Count = m_buyTrades.Count + 1;
                    m_buyTrades.Volume = m_buyTrades.Volume + thisPos.Volume;
                    m_buyTrades.CumulativeValue = m_buyTrades.CumulativeValue + (thisPos.Volume * thisPos.EntryPrice);
                    if (thisPos.EntryPrice > m_buyTrades.HighestPrice)
                        m_buyTrades.HighestPrice = thisPos.EntryPrice;
                    if ((thisPos.EntryPrice < m_buyTrades.LowestPrice) || (m_buyTrades.LowestPrice == 0.0))
                    {
                        m_buyTrades.LowestPrice = thisPos.EntryPrice;
                        m_buyTrades.LastVolume = thisPos.Volume;
                    }
                    if (thisPos.EntryTime > m_buyTrades.LastTradeTime)
                        m_buyTrades.LastTradeTime = thisPos.EntryTime;
                    m_buyTrades.Commission += (thisPos.Commissions + thisPos.Swap + thisPos.Commissions);
                }
                else if (thisPos.TradeType == TradeType.Sell)
                {
                    m_sellTrades.Count = m_sellTrades.Count + 1;
                    m_sellTrades.Volume = m_sellTrades.Volume + thisPos.Volume;
                    m_sellTrades.CumulativeValue = m_sellTrades.CumulativeValue + (thisPos.Volume * thisPos.EntryPrice);
                    if (thisPos.EntryPrice > m_sellTrades.HighestPrice)
                    {
                        m_sellTrades.HighestPrice = thisPos.EntryPrice;
                        m_sellTrades.LastVolume = thisPos.Volume;
                    }
                    if ((thisPos.EntryPrice < m_sellTrades.LowestPrice) || (m_sellTrades.LowestPrice == 0.0))
                        m_sellTrades.LowestPrice = thisPos.EntryPrice;
                    if (thisPos.EntryTime > m_sellTrades.LastTradeTime)
                        m_sellTrades.LastTradeTime = thisPos.EntryTime;
                    m_sellTrades.Commission += (thisPos.Commissions + thisPos.Swap + thisPos.Commissions);
                }
            }
            if (m_buyTrades.Count > 0)
            {
                m_buyTrades.AveragePrice = m_buyTrades.CumulativeValue / m_buyTrades.Volume;
                m_buyTrades.TargetPrice = m_buyTrades.AveragePrice + AverageTP * Symbol.PipSize;
            }
            if (m_sellTrades.Count > 0)
            {
                m_sellTrades.AveragePrice = m_sellTrades.CumulativeValue / m_sellTrades.Volume;
                m_sellTrades.TargetPrice = m_sellTrades.AveragePrice - AverageTP * Symbol.PipSize;
            }

            for (int i = 0; i < PendingOrders.Count; i++)
            {
                PendingOrder thisOrder = PendingOrders[i];
                if (thisOrder.SymbolCode != Symbol.Code)
                    continue;
                if (thisOrder.Label != LABEL)
                    continue;
                if (thisOrder.OrderType != PendingOrderType.Stop)
                    continue;
                if (thisOrder.TradeType == TradeType.Buy)
                {
                    m_buyTrades.PendingCount++;
                    if (thisOrder.TargetPrice > m_buyTrades.HighestPrice)
                        m_buyTrades.HighestPrice = thisOrder.TargetPrice;
                    if ((thisOrder.TargetPrice < m_buyTrades.LowestPrice) || (m_buyTrades.LowestPrice == 0.0))
                    {
                        m_buyTrades.LowestPrice = thisOrder.TargetPrice;
                        m_buyTrades.LastVolume = thisOrder.Volume;
                    }
                }
                else if (thisOrder.TradeType == TradeType.Sell)
                {
                    m_sellTrades.PendingCount++;
                    if (thisOrder.TargetPrice > m_sellTrades.HighestPrice)
                    {
                        m_sellTrades.HighestPrice = thisOrder.TargetPrice;
                        m_sellTrades.LastVolume = thisOrder.Volume;
                    }
                    if ((thisOrder.TargetPrice < m_sellTrades.LowestPrice) || (m_sellTrades.LowestPrice == 0.0))
                        m_sellTrades.LowestPrice = thisOrder.TargetPrice;
                }
            }

            m_buyTrades.LastTradeTime = getCandleOpenTime(m_buyTrades.LastTradeTime);
            m_sellTrades.LastTradeTime = getCandleOpenTime(m_sellTrades.LastTradeTime);

            if ((m_buyTrades.Count == 0) && (m_buyTrades.PendingCount > 0))
                deletePendingStopOrders(TradeType.Buy);
            if ((m_sellTrades.Count == 0) && (m_sellTrades.PendingCount > 0))
                deletePendingStopOrders(TradeType.Sell);
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // evaluateStops
        // Evaluate Trailing Stop of open positions.
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        private void evaluateStops()
        {
            if (!TS_Enabled)
                return;
            int posCount = Positions.Count;
            for (int i = posCount - 1; i >= 0; i--)
            {
                Position thisPos = Positions[i];
                if ((thisPos.SymbolCode != Symbol.Code) || (thisPos.Label != LABEL))
                    continue;
                if ((thisPos.Pips < m_TsPips) || (thisPos.NetProfit <= 0.0))
                    continue;
                bool mustUpdate = false;
                double? newSL = thisPos.StopLoss;
                if (thisPos.TradeType == TradeType.Buy)
                {
                    newSL = Math.Max(Symbol.Bid - TS_Distance * Symbol.PipSize, thisPos.EntryPrice);
                    if (TS_Trigger > 0)
                        newSL = Math.Max(newSL.Value, thisPos.EntryPrice + TS_Trigger * Symbol.PipSize);
                    if (thisPos.StopLoss.HasValue)
                        mustUpdate = (newSL > thisPos.StopLoss);
                    else
                        mustUpdate = true;
                }
                else
                {
                    newSL = Math.Min(Symbol.Ask + TS_Distance * Symbol.PipSize, thisPos.EntryPrice);
                    if (TS_Trigger > 0)
                        newSL = Math.Min(newSL.Value, thisPos.EntryPrice - TS_Trigger * Symbol.PipSize);
                    if (thisPos.StopLoss.HasValue)
                        mustUpdate = (newSL < thisPos.StopLoss);
                    else
                        mustUpdate = true;
                }
                if (mustUpdate)
                    safe_ModifyPosition(thisPos, newSL, thisPos.TakeProfit);
            }
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // safe_ModifyPosition
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        private bool safe_ModifyPosition(Position posToModify, double? newSL, double? newTP)
        {
            if ((formatPrice(newSL) == formatPrice(posToModify.StopLoss)) && (formatPrice(newTP) == formatPrice(posToModify.TakeProfit)))
                return true;

            double? oldSL = posToModify.StopLoss;
            TradeResult resModify = ModifyPosition(posToModify, newSL, newTP);
            if (resModify.IsSuccessful)
            {
                Print("TRAILING STOP of {0} position ID #{1} modified from {2} to {3}.", posToModify.TradeType.ToString().ToUpper(), posToModify.Id, formatPrice(oldSL), formatPrice(newSL));
            }
            else
            {
                Print("ERROR : Trailing Stop of {0} position ID #{1} was NOT modified. SL[{2} to {3}]. Error {4}.", posToModify.TradeType.ToString().ToUpper(), posToModify.Id, formatPrice(oldSL), formatPrice(newSL), formatError(resModify.Error));
            }

            return resModify.IsSuccessful;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // formatPrice
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        private string formatPrice(double? value)
        {
            return (value.HasValue ? (double.IsNaN(value.Value) ? "NONE" : value.Value.ToString(FORMAT_PRICE)) : "NONE");
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // formatError
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        private string formatError(ErrorCode? err)
        {
            return (err.HasValue ? err.Value.ToString() : "UNKNOWN");
        }


        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // deletePendingStopOrders
        // Delete pending STOP orders of specific TradeType
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        private void deletePendingStopOrders(TradeType tradeType)
        {
            int totalOrders = PendingOrders.Count;
            for (int i = totalOrders - 1; i >= 0; i--)
            {
                PendingOrder thisOrder = PendingOrders[i];
                if (thisOrder.OrderType != PendingOrderType.Stop)
                    continue;
                if (thisOrder.SymbolCode != Symbol.Code)
                    continue;
                if (thisOrder.TradeType != tradeType)
                    continue;
                if (thisOrder.Label != LABEL)
                    continue;
                TradeResult result = CancelPendingOrder(thisOrder);
                if (!result.IsSuccessful)
                    Print("Could not delete pending Order #{0}. Error {1}", thisOrder.Id, (result.Error.HasValue ? result.Error.Value.ToString() : "UNKNOWN."));
            }
            evaluatePositions();
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // placeStopOrder
        // Place STOP order of specific type
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        private bool placeStopOrder(TradeType tradeType, double entryPrice, string refField, double refPrice, long volume, ref long ticket)
        {
            TradeResult result = PlaceStopOrder(tradeType, Symbol, volume, entryPrice, LABEL);
            if (result.IsSuccessful)
            {
                ticket = result.PendingOrder.Id;
                Print("Placed pending {0}-STOP order #{1} at {2} for {3} units. {4} price is {5}.", (tradeType == TradeType.Buy ? "BUY" : "SELL"), ticket, entryPrice.ToString(FORMAT_PRICE), volume, refField, refPrice.ToString(FORMAT_PRICE));
            }
            else
            {
                Print("Could not place {0}-STOP order at {1} for {2} units. Error - {3}", (tradeType == TradeType.Buy ? "BUY" : "SELL"), entryPrice.ToString(FORMAT_PRICE), volume, (result.Error.HasValue ? result.Error.Value.ToString() : "UNKNOWN."));
            }
            return result.IsSuccessful;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // placeMarketOrder
        // Place MARKET order of specific type
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        private bool placeMarketOrder(TradeType tradeType, long volume, ref long ticket)
        {
            TradeResult result = ExecuteMarketOrder(tradeType, Symbol, volume, LABEL);
            if (result.IsSuccessful)
            {
                ticket = result.Position.Id;
                Print("Placed initial market {0} order #{1} at {2} for {3} units.", (tradeType == TradeType.Buy ? "BUY" : "SELL"), ticket, result.Position.EntryPrice.ToString(FORMAT_PRICE), volume);
            }
            else
            {
                Print("Could not place inital {0} market order for {1} units. Error - {2}", (tradeType == TradeType.Buy ? "BUY" : "SELL"), volume, (result.Error.HasValue ? result.Error.Value.ToString() : "UNKNOWN"));
            }
            return result.IsSuccessful;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // getCandleOpenTime
        // Returns the opening time of the candle for the specified time.
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        private DateTime getCandleOpenTime(DateTime tradeTime)
        {
            DateTime candleOpenTime = DateTime.Now;
            for (int i = MarketSeries.OpenTime.Count - 1; i >= 0; i--)
            {
                if (MarketSeries.OpenTime.Last(i) <= tradeTime)
                    candleOpenTime = MarketSeries.OpenTime.Last(i);
            }
            return candleOpenTime;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // placeInitialGridOrders
        // Place initial orders of the GRID if conditions are met.
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        private void placeInitialGridOrders()
        {
            if (Buy && (m_buyTrades.Count == 0) && (MarketSeries.Close.Last(1) > MarketSeries.Close.Last(2)))
            {
                evaluatePositions();
                if (m_buyTrades.Count == 0)
                {
                    long buyPositionID = 0;
                    if (placeMarketOrder(TradeType.Buy, Symbol.NormalizeVolume(FirstVolume), ref buyPositionID))
                    {
                        m_buyTrades.LastTradeTime = getCandleOpenTime(Server.Time);
                        evaluatePositions();
                    }
                }
            }
            if (Sell && (m_sellTrades.Count == 0) && (MarketSeries.Close.Last(2) > MarketSeries.Close.Last(1)))
            {
                evaluatePositions();
                if (m_sellTrades.Count == 0)
                {
                    long sellPositionID = 0;
                    if (placeMarketOrder(TradeType.Sell, Symbol.NormalizeVolume(FirstVolume), ref sellPositionID))
                    {
                        m_sellTrades.LastTradeTime = getCandleOpenTime(Server.Time);
                        evaluatePositions();
                    }
                }
            }
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // runGrid
        // Run the main GRID logic after initial position is opened.
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        private void runGrid()
        {
            DateTime currentCandleTime = MarketSeries.OpenTime.Last(0);
            if (Buy && (m_buyTrades.Count > 0) && (Symbol.Ask < m_buyTrades.LowestPrice))
            {
                bool canTrade = true;
                if (OneTradePerCandle && (m_buyTrades.LastTradeTime >= currentCandleTime))
                    canTrade = false;
                if ((Symbol.Ask <= m_buyTrades.LowestPrice - (StopOrderDistance + PipStep) * Symbol.PipSize) && canTrade)
                {
                    long buyTicketID = 0;
                    long buyVolume = Symbol.NormalizeVolume(m_buyTrades.LastVolume * VolumeExponent);
                    double buyTargetPrice = Math.Min(Symbol.Ask + StopOrderDistance * Symbol.PipSize, m_buyTrades.LowestPrice - PipStep * Symbol.PipSize);
                    if (placeStopOrder(TradeType.Buy, Math.Round(buyTargetPrice, Symbol.Digits), "ASK", Symbol.Ask, buyVolume, ref buyTicketID))
                    {
                        m_buyTrades.LastTradeTime = currentCandleTime;
                        evaluatePositions();
                    }
                }
            }
            if (Sell && (m_sellTrades.Count > 0) && (Symbol.Bid > m_sellTrades.HighestPrice))
            {
                if (OneTradePerCandle && (m_sellTrades.LastTradeTime >= currentCandleTime))
                    return;
                if (Symbol.Bid >= m_sellTrades.HighestPrice + (StopOrderDistance + PipStep) * Symbol.PipSize)
                {
                    long sellTicketID = 0;
                    long sellVolume = Symbol.NormalizeVolume(m_sellTrades.LastVolume * VolumeExponent);
                    double sellTargetPrice = Math.Max(Symbol.Bid - StopOrderDistance * Symbol.PipSize, m_sellTrades.HighestPrice + PipStep * Symbol.PipSize);
                    if (placeStopOrder(TradeType.Sell, Math.Round(sellTargetPrice, Symbol.Digits), "BID", Symbol.Bid, sellVolume, ref sellTicketID))
                    {
                        m_sellTrades.LastTradeTime = currentCandleTime;
                        evaluatePositions();
                    }
                }
            }
        }


        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // updateTakeProfit
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        private void updateTakeProfit(TradeType tradeType, double newTP)
        {
            foreach (var position in Positions)
            {
                if (position.Label == LABEL && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == tradeType)
                    {
                        if (!position.TakeProfit.HasValue)
                            ModifyPosition(position, position.StopLoss, newTP);
                        else if (newTP.ToString(FORMAT_PRICE) != position.TakeProfit.Value.ToString(FORMAT_PRICE))
                            ModifyPosition(position, position.StopLoss, newTP);
                    }
                }
            }
        }


        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // drawGraphics
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        private void drawGraphics()
        {
            if (m_buyTrades.Count > 1)
                ChartObjects.DrawHorizontalLine("bpoint", m_buyTrades.AveragePrice, Colors.Yellow, 2, LineStyle.Dots);
            else
                ChartObjects.RemoveObject("bpoint");
            if (m_sellTrades.Count > 1)
                ChartObjects.DrawHorizontalLine("spoint", m_sellTrades.AveragePrice, Colors.HotPink, 2, LineStyle.Dots);
            else
                ChartObjects.RemoveObject("spoint");
            double openPL = 0.0;

            string buyInfo = "", sellInfo = "";
            if (m_buyTrades.Count > 0)
            {
                double buyPL = m_buyTrades.Volume * Symbol.PipValue * (Symbol.Bid - m_buyTrades.AveragePrice) / Symbol.PipSize + m_buyTrades.Commission;
                openPL += buyPL;
                buyInfo = string.Format("\nBUY : {0} trades. {1} units.\nBUY Average : {2}.\nBUY Target : {3} pips.\nBUY P/L : {4} {5}.", m_buyTrades.Count, m_buyTrades.Volume, m_buyTrades.AveragePrice.ToString(FORMAT_PRICE), (Math.Round((m_buyTrades.TargetPrice - Symbol.Bid) / Symbol.PipSize, 1)).ToString("N1"), buyPL.ToString("N2"), m_Currency);
            }
            if (m_sellTrades.Count > 0)
            {
                double sellPL = m_sellTrades.Volume * Symbol.PipValue * (m_sellTrades.AveragePrice - Symbol.Ask) / Symbol.PipSize + m_sellTrades.Commission;
                openPL += sellPL;
                sellInfo = string.Format("\nSELL : {0} trades. {1} units.\nSELL Average : {2}.\nSELL Target : {3} pips.\nSELL P/L : {4} {5}.", m_sellTrades.Count, m_sellTrades.Volume, m_sellTrades.AveragePrice.ToString(FORMAT_PRICE), (Math.Round((Symbol.Ask - m_sellTrades.TargetPrice) / Symbol.PipSize, 1)).ToString("N1"), sellPL.ToString("N2"), m_Currency);
            }
            string panelText = string.Format("Spread : {0} pips.\nOpen P/L : {1} {4}.{2}{3}", (Symbol.Spread / Symbol.PipSize).ToString("N1"), openPL.ToString("N2"), buyInfo, sellInfo, m_Currency);
            ChartObjects.DrawText("panel", panelText, StaticPosition.TopLeft, Colors.White);
        }
    }
}

 

Comments
Log in to add a comment.
TradeMingZhi's avatar
TradeMingZhi · 5 years ago

doubling your position everytime that pips pass 10, 20, 30, 40 may seem unwise.

you will make your position 16x bigger at 40 pips profit for example

do you mean it to be 2x at 10, 3x at 20, 4x at 30, 5x at 40 instead?

TradeMingZhi's avatar
TradeMingZhi · 5 years ago

check your email