Getting exact money value of stop loss

Created at 06 Jan 2024, 18:43
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!
CH

ChrisSpire

Joined 12.12.2022

Getting exact money value of stop loss
06 Jan 2024, 18:43


I want to sum money value of all stop losses in open positions (total currency risk of open positions). How do I get the exact money value that is displayed next to “pips” on the stop loss label?

Symbol.AmountRisked(Volume, StopLossInPips)

or 

Symbol.AmountRisked(Volume, StopLossInPips) + Position.Commisions;

does not give the value that is displayed on the stop loss line label in cTrader.

Step by step approach, such as below (for BUY position) or similair, does not give results too:

var StopLossInPips = ((Position.StopLoss - Position.EntryPrice)/Symbol.PipSize);var StopLossAmount = StopLossInPips * (Symbol.PipValue/Symbol.PipSize * 100000);

 


@ChrisSpire
Replies

ctrader.guru
07 Jan 2024, 09:21

I am not sure I understand what you mean but I will try to answer with a concrete example and maybe start from this example to better understand what you need:

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

namespace cAlgo.Robots
{

    [Robot(AccessRights = AccessRights.None)]
    public class TradesRisky : Robot
    {

        class Risky
        {

            public double Pips { get; set; }
            public double Commissions { get; set; }

        }

        protected override void OnStart()
        {

            Positions.Modified += OnPositionModified;
            UpdateData();

        }

        protected override void OnTick()
        {

            UpdateData();

        }

        public void OnPositionModified(PositionModifiedEventArgs args)
        {

            UpdateData();

        }

        private void UpdateData() {

            Risky MyRisky = GetTotalPipsRisky();
            double MoneyRisky = GetPipValueInMoney(MyRisky.Pips);

            Chart.DrawStaticText("Risky",
                                 string.Format("You are risking {0} pips for a total value of {1} {2} and {3} {2} commissions.", MyRisky.Pips, MoneyRisky, Account.Asset, MyRisky.Commissions),
                                 VerticalAlignment.Top,
                                 HorizontalAlignment.Left,
                                 Color.Red
                                 );

        }

        // This function can be improved
        private double GetPipValueInMoney(double pips)
        {

            return Math.Round(pips * Symbol.PipValue / ( Symbol.PipSize * 100), 2);

        }

        private Risky GetTotalPipsRisky()
        {

            double pips = 0;
            double commissions = 0;

            Position[] MyPositions = Positions.FindAll(null, SymbolName);

            foreach (Position position in Positions)
            {

                if (position.StopLoss != null && position.StopLoss > 0) pips += Math.Abs((double)position.StopLoss - position.EntryPrice);

                commissions += position.Commissions;

            }

            return new Risky
            {

                Pips = DigitsToPips(pips),
                Commissions = commissions

            };

        }

        private double DigitsToPips(double pips)
        {

            return Math.Round(pips / Symbol.PipSize, 2);

        }

    }

}

@ctrader.guru

ChrisSpire
07 Jan 2024, 11:05

RE: Getting exact currecny value of stop loss

That is exactly my goal, thank you. 

Nevertheless your example still gives me different values. See screenshot (backtesting) below based on copy/paste of your code to new cBot with just ExecuteMarketOrder added;

ctrader.guru said: 

I am not sure I understand what you mean but I will try to answer with a concrete example and maybe start from this example to better understand what you need:

using cAlgo.API;using cAlgo.API.Internals;using System;namespace cAlgo.Robots{    [Robot(AccessRights = AccessRights.None)]    public class TradesRisky : Robot    {        class Risky        {            public double Pips { get; set; }            public double Commissions { get; set; }        }        protected override void OnStart()        {            Positions.Modified += OnPositionModified;            UpdateData();        }        protected override void OnTick()        {            UpdateData();        }        public void OnPositionModified(PositionModifiedEventArgs args)        {            UpdateData();        }        private void UpdateData() {            Risky MyRisky = GetTotalPipsRisky();            double MoneyRisky = GetPipValueInMoney(MyRisky.Pips);            Chart.DrawStaticText("Risky",                                 string.Format("You are risking {0} pips for a total value of {1} {2} and {3} {2} commissions.", MyRisky.Pips, MoneyRisky, Account.Asset, MyRisky.Commissions),                                 VerticalAlignment.Top,                                 HorizontalAlignment.Left,                                 Color.Red                                 );        }        // This function can be improved        private double GetPipValueInMoney(double pips)        {            return Math.Round(pips * Symbol.PipValue / ( Symbol.PipSize * 100), 2);        }        private Risky GetTotalPipsRisky()        {            double pips = 0;            double commissions = 0;            Position[] MyPositions = Positions.FindAll(null, SymbolName);            foreach (Position position in Positions)            {                if (position.StopLoss != null && position.StopLoss > 0) pips += Math.Abs((double)position.StopLoss - position.EntryPrice);                commissions += position.Commissions;            }            return new Risky            {                Pips = DigitsToPips(pips),                Commissions = commissions            };        }        private double DigitsToPips(double pips)        {            return Math.Round(pips / Symbol.PipSize, 2);        }    }}

 


@ChrisSpire

ctrader.guru
07 Jan 2024, 12:49

Which pair?


@ctrader.guru

ctrader.guru
07 Jan 2024, 16:20

Now I think I understand, you have to change your approach, I added some tricks:

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

namespace cAlgo.Robots
{

    [Robot(AccessRights = AccessRights.FullAccess)]
    public class TradesRisky : Robot
    {

        class Risky
        {

            public double Pips { get; set; }
            public double Commissions { get; set; }

            public double Lots { get; set; }

        }

        [Parameter("Lots", Group = "Visual BackTest", MinValue = 0.01, DefaultValue = 0.37)]
        public double MyLots { get; set; }

        [Parameter("Stop Loss Take Profit", Group = "Visual BackTest", MinValue = 0, DefaultValue = 50)]
        public double MyStops { get; set; }

        protected override void OnStart()
        {

            Positions.Closed += OnPositionClosed;
            Positions.Opened += OnPositionOpened;
            Positions.Modified += OnPositionModified;
            UpdateData();

            // Open a new trade for testing visual mode
            if (RunningMode == RunningMode.VisualBacktesting) ExecuteMarketOrder(TradeType.Buy, SymbolName, Symbol.QuantityToVolumeInUnits(MyLots), null, MyStops, MyStops);

        }

        protected override void OnTick()
        {

            UpdateData();

        }

        public void OnPositionClosed(PositionClosedEventArgs args)
        {

            UpdateData();

        }

        public void OnPositionOpened(PositionOpenedEventArgs args)
        {

            UpdateData();

        }

        public void OnPositionModified(PositionModifiedEventArgs args)
        {

            UpdateData();

        }

        // Only if stoploss is set
        private void UpdateData()
        {

            int trades = 0;
            double pips = 0;
            double lots = 0;
            double money = 0;
            double commissions = 0;

            Position[] MyPositions = Positions.FindAll(null, SymbolName);

            foreach (Position position in Positions)
            {

                if (position.StopLoss != null && position.StopLoss > 0)
                {

                    trades++;
                    double currentstoploss = DigitsToPips( Math.Abs((double)position.StopLoss - position.EntryPrice) );
                    pips += currentstoploss;
                    lots += position.Quantity;
                    money += GetPipValueInMoney(currentstoploss, position.Quantity);
                    commissions += Math.Abs(Math.Round(position.Commissions, 2) * 2);

                }

            }

            pips = Math.Round(pips, 2);
            lots = Math.Round(lots, 2);
            money = Math.Round(money, 2);
            commissions = Math.Round(commissions, 2);

            Chart.DrawStaticText("Trades", string.Format("Trades: {0}", trades), VerticalAlignment.Top,HorizontalAlignment.Left, Color.Red );
            Chart.DrawStaticText("Pips", string.Format("\r\nPips: {0}", pips), VerticalAlignment.Top, HorizontalAlignment.Left, Color.Red);
            Chart.DrawStaticText("Lots", string.Format("\r\n\r\nLots: {0}", lots), VerticalAlignment.Top, HorizontalAlignment.Left, Color.Red);
            Chart.DrawStaticText("Money", string.Format("\r\n\r\n\r\nRisk: {0}", money), VerticalAlignment.Top, HorizontalAlignment.Left, Color.Red);
            Chart.DrawStaticText("Commissions", string.Format("\r\n\r\n\r\n\r\nCommissions: {0}", commissions), VerticalAlignment.Top, HorizontalAlignment.Left, Color.Red);
            Chart.DrawStaticText("Total Risk", string.Format("\r\n\r\n\r\n\r\n\r\nTotal Risk: {0}", Math.Round(money + commissions, 2)), VerticalAlignment.Top, HorizontalAlignment.Left, Color.Red);

        }

        // This function can be improved
        private double GetPipValueInMoney(double pips, double lots)
        {

            double all_microlots = Math.Round(lots / 0.01, 2);
            double multy = 100;

            switch (Symbol.Digits)
            {

                case 3:

                    multy = 0.1;
                    break;

                case 4:
                case 5:
                    multy = 10;
                    break;

            }

            return Math.Round(pips * ( Symbol.PipValue / (Symbol.PipSize * multy) ) * all_microlots, 2);

        }

        private double DigitsToPips(double pips)
        {

            return Math.Round(pips / Symbol.PipSize, 2);

        }

    }

}

@ctrader.guru

ctrader.guru
07 Jan 2024, 16:24

You can also remove the class that is no longer needed now:

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

namespace cAlgo.Robots
{

    [Robot(AccessRights = AccessRights.FullAccess)]
    public class TradesRisky : Robot
    {               

        [Parameter("Lots", Group = "Visual BackTest", MinValue = 0.01, DefaultValue = 0.37)]
        public double MyLots { get; set; }

        [Parameter("Stop Loss Take Profit", Group = "Visual BackTest", MinValue = 0, DefaultValue = 50)]
        public double MyStops { get; set; }

        protected override void OnStart()
        {

            Positions.Closed += OnPositionClosed;
            Positions.Opened += OnPositionOpened;
            Positions.Modified += OnPositionModified;
            UpdateData();

            // Open a new trade for testing visual mode
            if (RunningMode == RunningMode.VisualBacktesting) ExecuteMarketOrder(TradeType.Buy, SymbolName, Symbol.QuantityToVolumeInUnits(MyLots), null, MyStops, MyStops);

        }

        protected override void OnTick()
        {

            UpdateData();

        }

        public void OnPositionClosed(PositionClosedEventArgs args)
        {

            UpdateData();

        }

        public void OnPositionOpened(PositionOpenedEventArgs args)
        {

            UpdateData();

        }

        public void OnPositionModified(PositionModifiedEventArgs args)
        {

            UpdateData();

        }

        // Only if stoploss is set
        private void UpdateData()
        {

            int trades = 0;
            double pips = 0;
            double lots = 0;
            double money = 0;
            double commissions = 0;

            Position[] MyPositions = Positions.FindAll(null, SymbolName);

            foreach (Position position in Positions)
            {

                if (position.StopLoss != null && position.StopLoss > 0)
                {

                    trades++;
                    double currentstoploss = DigitsToPips( Math.Abs((double)position.StopLoss - position.EntryPrice) );
                    pips += currentstoploss;
                    lots += position.Quantity;
                    money += GetPipValueInMoney(currentstoploss, position.Quantity);
                    commissions += Math.Abs(Math.Round(position.Commissions, 2) * 2);

                }

            }

            pips = Math.Round(pips, 2);
            lots = Math.Round(lots, 2);
            money = Math.Round(money, 2);
            commissions = Math.Round(commissions, 2);

            Chart.DrawStaticText("Trades", string.Format("Trades: {0}", trades), VerticalAlignment.Top,HorizontalAlignment.Left, Color.Red );
            Chart.DrawStaticText("Pips", string.Format("\r\nPips: {0}", pips), VerticalAlignment.Top, HorizontalAlignment.Left, Color.Red);
            Chart.DrawStaticText("Lots", string.Format("\r\n\r\nLots: {0}", lots), VerticalAlignment.Top, HorizontalAlignment.Left, Color.Red);
            Chart.DrawStaticText("Money", string.Format("\r\n\r\n\r\nRisk: {0}", money), VerticalAlignment.Top, HorizontalAlignment.Left, Color.Red);
            Chart.DrawStaticText("Commissions", string.Format("\r\n\r\n\r\n\r\nCommissions: {0}", commissions), VerticalAlignment.Top, HorizontalAlignment.Left, Color.Red);
            Chart.DrawStaticText("Total Risk", string.Format("\r\n\r\n\r\n\r\n\r\nTotal Risk: {0}", Math.Round(money + commissions, 2)), VerticalAlignment.Top, HorizontalAlignment.Left, Color.Red);

        }

        // This function can be improved
        private double GetPipValueInMoney(double pips, double lots)
        {

            double all_microlots = Math.Round(lots / 0.01, 2);
            double multy = 100;

            switch (Symbol.Digits)
            {

                case 3:

                    multy = 0.1;
                    break;

                case 4:
                case 5:
                    multy = 10;
                    break;

            }

            return Math.Round(pips * ( Symbol.PipValue / (Symbol.PipSize * multy) ) * all_microlots, 2);

        }

        private double DigitsToPips(double pips)
        {

            return Math.Round(pips / Symbol.PipSize, 2);

        }

    }

}

@ctrader.guru

ChrisSpire
03 Feb 2024, 15:51

RE: Getting exact money value of stop loss

ctrader.guru said: 

You can also remove the class that is no longer needed now:

(...)

Thank you! Sorry for bugging but I still need some adjustment for indices. I get wrong results (they are 10x too big) for GER40 or US100. Methods name have changed but the code inside is the same as yours.

I added another variant for 2 digits:

        switch (cBot.Symbol.Digits)
        {
            case 2:
                multy = 1000;
                break;
            case 3:
                multy = 0.1;
                break;
            case 4:
            case 5:
                multy = 10;
                break;
        }

But now XAUUSD is broken (gives 10x to small result). Is there a way to do this properly or I should make adjustments for each symbol (sound quite insane)?

 


@ChrisSpire