Topics
Replies

firemyst
21 Feb 2024, 01:38

RE: RE: Amount to trade depending on stop loss

oliver.r.m.92 said: 

 

I have rewritten the code and used your part of code but now I have a new problem, in the log it shows this message: Crashed in OnBar with ArgumentOutOfRangeException: Specified argument was out of the range of valid values. Parameter name: volume. Actual value was: NaN.

The new code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class MACDcBot : Robot
    {
        private bool isPositionOpen;
        private MacdCrossOver _MACD;
        private MovingAverage EMA;
        private const string label = "Trade ON";
        private double stopLossPrice;

        //MA                
        [Parameter("Source", Group = "Moving Average")]
        public DataSeries SourceSeries { get; set; }

        [Parameter("MA Type", Group = "Moving Average")]
        public MovingAverageType MAType { get; set; }

        [Parameter("MA Periods", Group = "Moving Average", DefaultValue = 200)]
        public int MAPeriods { get; set; }

        //MACD
        [Parameter("Period", DefaultValue = 9)]
        public int Period { get; set; }

        [Parameter("Long Cycle", DefaultValue = 26)]
        public int LongCycle { get; set; }

        [Parameter("Short Cycle", DefaultValue = 12)]
        public int ShortCycle { get; set; }

        [Parameter("Signal-line crossover true:if Signal-line crossover false: Zero crossover", DefaultValue = true)]
        public bool IsSignalLineCrossover { get; set; }

        protected override void OnStart()
        {
            _MACD = Indicators.MacdCrossOver(LongCycle, ShortCycle, Period);
            EMA = Indicators.MovingAverage(SourceSeries, MAPeriods, MAType);
            isPositionOpen = false;
            Positions.Closed += OnPositionsClosed;
        }

        protected override void OnBar()
        {           
            if (Positions.Count > 0)
            {
                var position = Positions.LastOrDefault();

                if (position != null)
                {
                    if (position.TradeType == TradeType.Buy)
                        stopLossPrice = EMA.Result.LastValue - Symbol.PipSize * 2; // 2 pips por debajo de la SMA de 200
                    else if (position.TradeType == TradeType.Sell)
                        stopLossPrice = EMA.Result.LastValue + Symbol.PipSize * 2; // 2 pips por encima de la SMA de 200

                    double takeProfitPrice = position.EntryPrice + (position.EntryPrice - stopLossPrice) * 1.5;

                    ModifyPosition(position, stopLossPrice, takeProfitPrice);
                }
            }

            // Calcula el tamaño de posición basado en el riesgo
            var maxAmountRisked = Account.Equity * (1 / 100);
            var positionSize = Symbol.NormalizeVolumeInUnits(maxAmountRisked / (stopLossPrice * Symbol.PipValue), RoundingMode.Down);
            
            if (IsSignalLineCrossover)
            {
                if (!isPositionOpen && _MACD.Histogram.LastValue > 0 && _MACD.Signal.LastValue < 0 && _MACD.MACD.Last(3) < _MACD.Signal.Last(3) && _MACD.MACD.Last(2) > _MACD.Signal.Last(2) && Bars.HighPrices.Last(1) > EMA.Result.Last(3))
                {
                    ExecuteMarketOrder(TradeType.Buy, SymbolName, positionSize, label);
                    isPositionOpen = true;
                }

                if (!isPositionOpen && _MACD.Histogram.LastValue < 0 && _MACD.Signal.LastValue > 0 && _MACD.MACD.Last(3) > _MACD.Signal.Last(3) && _MACD.MACD.Last(2) < _MACD.Signal.Last(2) && Bars.LowPrices.Last(1) < EMA.Result.Last(3))
                {
                    ExecuteMarketOrder(TradeType.Sell, SymbolName, positionSize, label);
                    isPositionOpen = true;
                }
            }
        }

        private void OnPositionsClosed(PositionClosedEventArgs args)
        {
            isPositionOpen = false;
        }
    }
}

 

Of course it throws an error. Look at your code in OnBar.

Look at the code you ALWAYS execute regardless if you're in a position or not. 

Where do you set stopLossPrice (I bolded it in the code above) if you don't have any positions? You're trying to do a calculation using it when you're not setting it.

 

I also suggest you starting learning how to use Print statements in your code to print values to the log. THen if you put print statements everywhere, you also know where your code is crashing.

 


@firemyst

firemyst
21 Feb 2024, 01:25

I don't understand what you're saying. Read that sentence outloud to yourself, especially the italics part:

“You can see here although in the code the close of bar 2 should be greater than or equal to the open of bar 3 but in this pic its tell yet the Bot still took the trade .”
 

In the screen capture you provided, the close of 2 bars back is greater than the close of the 3rd bar back from the current bar.


@firemyst

firemyst
21 Feb 2024, 01:16

Yes it can. You'll have to implement checks. There's no way currently to prevent a user from manually modify an order (SL/TP), but you can always keep track of the last value your bot moved it too and then revert back to those values if they were updated.

 

Other modifications like increasing/decreasing the position size and such will be a bit more tricky because you'll first have to start by asking yourself… if someone manually decreased your position size, would you really want to increase it back to where it was?

 


@firemyst

firemyst
15 Feb 2024, 03:53

I'm not sure how you could account for that? Would be interesting to know if it can be done.

For instance, do you know what the lag time will be between the time your bot places an order, when the server receives your order, and when it's actually executed? 

You could be doing a replay at a time when the market is closed, or very slow, and thus little lag; whereas when you run your bot it may be during peak trading hours and could be lots of internet congestion.


@firemyst

firemyst
13 Feb 2024, 01:02

Just choose to export your history as an Excel file and then save that file as a CSV.


@firemyst

firemyst
13 Feb 2024, 00:46

#1 you an already do. Just go to the update order screen and reduce the number of lots/units you have, and/or set a smart “take profit” level. 


@firemyst

firemyst
13 Feb 2024, 00:39 ( Updated at: 13 Feb 2024, 00:44 )

Are you able to provide screen captures of your back-test parameters?

 

Also, I don't believe async trade operations are fully supported in backtest or work as expected in backtest by their very nature… eg, in backtest mode, everything is “instantaneous” as opposed to live markets where one async call may execute right away, others will have a delay, etc etc.


@firemyst

firemyst
13 Feb 2024, 00:36

What time frame are you using?

You don't say, and that's what's causing your issue. 

 

Obviously that will make a difference. Your default lookback period is 1000. So if you're on a weekly, daily, 4-hourly, 200 Renko, 100-range, 2/3/4 hour HA, etc etc, you won't have more bars than your lookback period, so your “else” logic never gets executed.

 if (index < LookbackPeriod)
    {
        RenkoTop[index] = double.NaN;
        RenkoBottom[index] = double.NaN;
        CurrentBrick[index] = double.NaN;
        return;
    }
    
    			// HOW DO YOU EXPECT THIS LOGIC TO EVER BE EXECUTED
    			// with a 1000 lookback period when you
    			//have less than 1000 (default lookback period) bars on the chart?
    			//Unless you get more than 1000 bars/candles on a chart, index
    			//will always be less than the lookback period except in 1 case.
    			
     double atrValue = _atr.Result[index];
    _brickSize = atrValue;

if (index == LookbackPeriod)
    {
        RenkoTop[index] = Bars.ClosePrices[index];
        RenkoBottom[index] = Bars.ClosePrices[index] - _brickSize;
        _isAscending = Bars.ClosePrices[index] > Bars.ClosePrices[index - 1];
    }
    else
    {

    }

 

You should debug your code by putting in lots of print statements to see where it's getting to, and what parts of your logic are or are not being executed.

 


@firemyst

firemyst
11 Feb 2024, 12:32

You know the candle's closing time because it's almost exactly the next candle's open time regardless of the time frame or chart you use - a new candle won't open unless the previous candle has closed.


@firemyst

firemyst
11 Feb 2024, 12:27

Use the DrawText and select a unicode character. Visual Studio will support these, as I have a few in my code:

        private const string CONST_StatusLong = "▲";
       //"↑"; //"▲"; //"⬆"; //"↑";
       private const string CONST_StatusShort = "▼";
       //"▼"; //"⬇"; //"↓";

Hopefully you can copy/paste those and they'll work in your code.


@firemyst

firemyst
04 Feb 2024, 04:14 ( Updated at: 05 Feb 2024, 06:57 )

You've posted this in the wrong forum.

Try here: 

https://ctrader.com/forum/calgo-support

 

To do the first thing you want, just loop through all open positions, and sum up the “Pips” property of each position:

double totalPips = 0;
foreach (Position p in Positions)
	totalPips += p.Pips;

@firemyst

firemyst
04 Feb 2024, 04:04 ( Updated at: 05 Feb 2024, 06:57 )

You should post your idea here:

 

https://ctrader.com/forum/suggestions

 


@firemyst

firemyst
28 Jan 2024, 11:55

What kind of text?

You don't say what kind of text you're wanting to align.

If you mean from the Chart.DrawText method, here's an example for you:

 ChartText ct = Chart.DrawText("position" + index, "hello world", entryPrice, textLocation, lineColor);
 ct.IsBold = true;
 ct.VerticalAlignment = VerticalAlignment.Center;
 ct.HorizontalAlignment = HorizontalAlignment.Left;
 ct.ZIndex = 15; //So it's above other objects on the chart and we can see it.

@firemyst

firemyst
24 Jan 2024, 02:11

//Get the historical trade stuff.
HistoricalTrade ht = History.FindLast(yourposition.Label, yourposition.SymbolName, yourposition.TradeType);

 


@firemyst

firemyst
23 Jan 2024, 09:51 ( Updated at: 23 Jan 2024, 12:55 )

Hello Team @Spotware / @PanagiotisCharalampous

Any further updates on a fix for this issue?

Thank you


@firemyst

firemyst
19 Jan 2024, 08:21

You can add the SL/TP columns in the “Trade watch” window under the chart if you're viewing that;

when you place an order, the SL and TP lines are on the chart, or can be dragged from the order's entry point to show on the chart.

So no idea what are you talking about???


@firemyst

firemyst
19 Jan 2024, 08:19

Instead of “step line”, how about using Renko candles since whatever Renko time frame you choose goes in even steps? 

 

Or do you want to specifically use it on something big like the daily time frame?


@firemyst

firemyst
13 Jan 2024, 13:47 ( Updated at: 15 Jan 2024, 07:11 )

My first suggestion is to post screen capture(s) showing the result of the build, because right now, for all we know you could be doing it in Visual Studio, VS Code, cTRader itself, or some other way. 

How are people supposed to know to be able to assist with the little info you provided?


@firemyst

firemyst
13 Jan 2024, 13:43 ( Updated at: 15 Jan 2024, 07:11 )

ThinkMarkets ThinkTrader has the best alert options for indicators, and I wish the team at Spotware would take notice how much cTrader is lacking in this area.


@firemyst

firemyst
13 Jan 2024, 13:41 ( Updated at: 15 Jan 2024, 07:11 )

You need to post this in the Suggestions forum if you would like this to be considered:

https://ctrader.com/forum/suggestions

 


@firemyst