Sending an order not at the bar 0

Questions about MultiCharts .NET and user contributed studies.
Livermore
Posts: 2
Joined: 06 Jul 2022

Sending an order not at the bar 0

Postby Livermore » 20 Oct 2023

I'm using Multicharts .NET
I tried to write a pattern (with 2 patterns): growth over a certain number of bars, then price a range over a certain number of bars. I don't understand why my order is sent on bar 0 on backtesting, at the beginning of the pattern (as if I can see the future). My pattern is identified correctly on the chart, but the order is sent not at the end of the price range, but at the beginning of the pattern on bar 0. Explain what the problem is?

Here's my code (I will provide an abbreviated code of the strategy and the code of two functions that define the pattern, I think it will be clear):

[Input]
public int bars_range {get;set;}
[Input]
public int bars_trend {get;set;}
[Input]
public double range_perc {get;set;}

protected override void CalcBar(){

//STRATEGY

if( Trend_Percent(Bars.Open[0],Bars.Close[bars_trend])>0.5
&& Trend_Percent(Bars.Open[0],Bars.Close[bars_trend])<1
&& Range_Percent(bars_trend+1,bars_range)<range_perc)
{
mkt_buy.Send();
}
if (StrategyInfo.MarketPosition != 0)
{
GenerateStopLoss(sl);
GenerateProfitTarget(tp);
}
else
{}
}

public double Range_Percent(int start_bar, int range_bar)
{
List<double> barss= new List<double>();
for(int i = start_bar; i < start_bar+range_bar; i++)
{
barss.Add(Bars.High);
barss.Add(Bars.Low);
}
double max_high = barss.Max();
double min_low = barss.Min();
double range = Math.Abs(max_high - min_low); // Разница между точками
return (range / max_high) * 100; // Процентная разница
}

public double Trend_Percent(double x, double y)
{
return 100*(y-x)/x;
}

HellGhostEvocatorX
Posts: 80
Joined: 10 Feb 2022
Has thanked: 52 times
Been thanked: 11 times

Re: Sending an order not at the bar 0

Postby HellGhostEvocatorX » 23 Oct 2023

So if I adapt your code snippet so that it runs at all, several buy orders will be triggered for me, and not at Bar 0. But without you posting the entire code, it will be difficult to help you... And with code snippets it is always difficult to work with and if they aren't even ready to run straight away, this is unnecessary work for those who want to help you. Please post the code here (and use the function for code here in the forum). Alternatively, use the built-in debug options in Multicharts (e.g. the output windows (or better yet, visual studio) to recreate your code. As a vague guess I think it is related to the use of "lists", in your example you shouldn't need them at all, Multicharts offers "VariableSeries" and e.g. Bars.High[]. The for loop is also not necessary,
When you call your "Range_Percent" method in the BarsCalc method, with each new bar your method is also called and its variables are updated. In general, the method they present does not work without adjustment.

Here is a code example for using the output window in multicharts editor:

Code: Select all

Output.WriteLine("Name------{0},{1}", yourVariable, Bars.FullSymbolData.Current);
replace yourVariable with the variable you want to observe, Bars.FullSymbolData.Current you know at which bar your variable changed.
When optimizing, please exclude the output function, otherwise Multicharts will unfortunately hang.
If the buy order at Bar 0 is already executed, its condition must already be true when you call the functions. If necessary, initialize the start values ​​of their variables in the Startcalc method.
and check out the tutorials on tradingcode.net.

Livermore
Posts: 2
Joined: 06 Jul 2022

Re: Sending an order not at the bar 0

Postby Livermore » 25 Oct 2023

you probably misunderstood me. My code runs well, the range and trend functions (price changes) are written correctly, trades are sent. My pattern on the chart is correct. But the problem is that the order is sent not after the pattern is formed, but on bar 0, as if I see what will happen in the future. I will attach a photo in which I show with a red arrow where the order was sent (on bar 0), and with a green arrow where it should be sent according to my logic. I will also attach the full code.


using System;
using System.Drawing;
using System.Linq;
using System.Threading;
using PowerLanguage.Function;
using ATCenterProxy.interop;
using System.Collections.Generic;

namespace PowerLanguage.Strategy {
public class TrendRange : SignalObject {
public TrendRange(object _ctx):base(_ctx)
{
sl = 3;
tp = 8;
bars_range = 5;
range_perc = 0.25;
bars_trend = 0;
trend_perc1 = 0.4;
trend_perc2 = 0.6;
}

//Market Order
private IOrderMarket mkt_buy;
private IOrderMarket mkt_sell;
private IOrderMarket mkt_buytocover;
private IOrderMarket mkt_sellshort;
//Limit Orders
private IOrderPriced limit_buy;
private IOrderPriced limit_sell;
private IOrderPriced limit_buytocover;
private IOrderPriced limit_sellshort;

[Input]
public double sl {get;set;}
[Input]
public double tp {get;set;}
[Input]
public int bars_range {get;set;}
[Input]
public double range_perc {get;set;}
[Input]
public int bars_trend {get;set;}
[Input]
public double trend_perc1 {get;set;}
[Input]
public double trend_perc2 {get;set;}


protected override void Create() {
//Market Order
mkt_buy = OrderCreator.MarketNextBar(new SOrderParameters(Contracts.Default, EOrderAction.Buy));
mkt_sell = OrderCreator.MarketNextBar(new SOrderParameters(Contracts.Default, EOrderAction.Sell));
mkt_buytocover = OrderCreator.MarketNextBar(new SOrderParameters(Contracts.Default, EOrderAction.BuyToCover));
mkt_sellshort = OrderCreator.MarketNextBar(new SOrderParameters(Contracts.Default, EOrderAction.SellShort));
//Limit Orders
limit_buy = OrderCreator.Limit(new SOrderParameters(Contracts.Default, EOrderAction.Buy));
limit_sell = OrderCreator.Limit(new SOrderParameters(Contracts.Default, EOrderAction.Sell));
limit_buytocover = OrderCreator.Limit(new SOrderParameters(Contracts.Default, EOrderAction.BuyToCover));
limit_sellshort = OrderCreator.Limit(new SOrderParameters(Contracts.Default, EOrderAction.SellShort));
}

protected override void StartCalc()
{

}

protected override void CalcBar(){

if(Trend_Percent(Bars.Open[0],Bars.Close[bars_trend])>trend_perc1
&& Trend_Percent(Bars.Open[0],Bars.Close[bars_trend])<trend_perc2
&& Range_Percent(bars_trend+1,bars_range)<range_perc)
{
mkt_buy.Send();
}

if (StrategyInfo.MarketPosition != 0)
{
GenerateStopLoss(sl);
GenerateProfitTarget(tp);
}
else
{}
}



public double max_high;
public double min_low;
public double Range_Percent(int start_bar, int range_bar)
{
List<double> barss= new List<double>();
for(int i = start_bar; i < start_bar+range_bar; i++)
{
barss.Add(Bars.High);
barss.Add(Bars.Low);
}
max_high = barss.Max();
min_low = barss.Min();
double range = Math.Abs(max_high - min_low);
return (range / max_high) * 100;

}

public double Trend_Percent(double x, double y)
{
return 100*(y-x)/x;
}
}
}
Attachments
MultiCharts .NET64 - Untitled Desktop 1- Test - [BTCUSDT - 5 Minutes - Binance].png
(25.61 KiB) Not downloaded yet
MultiCharts .NET64 - Untitled Desktop - Test - [BTCUSDT - 5 Minutes - Binance].png
(29.75 KiB) Not downloaded yet

HellGhostEvocatorX
Posts: 80
Joined: 10 Feb 2022
Has thanked: 52 times
Been thanked: 11 times

Re: Sending an order not at the bar 0

Postby HellGhostEvocatorX » 28 Oct 2023

Yes, it could be that I misunderstood them, since they don't seem to speak English and I'm not a native English speaker, misunderstandings can sometimes arise.
First of all, it is still not clear what you mean by Bar0. In your picture the bar is neither the first nor the last, so

1. why Bar0?

But your pictures shed some light on your problem.
But now I ask myself,

2. How do you know that according to your logic, the order should be sent on the bar with the green arrow?

3.
Are you aware that in your pictures the order was executed at the open of a bar. Since you are using buynextbar, the condition for your order (since you probably don't use IOG) will already be met one bar before your red arrow and will then be executed at the next bar.

I can't run your code without errors: I have to:

Code: Select all

barss.Add(Bars.High); barss.Add(Bars.Low);

to

Code: Select all

barss.Add(Bars.High[0]); barss.Add(Bars.Low[0]);


change.
4.
does this match your code?

Unfortunately, with your code and settings, I can not execute any orders on my symbol.

I added few lines to your code. Maybe you would like to run this again and send a new image of the areas already shown in the other image. (adjust the offsets if necessary) perhaps the output window of the bars in question would also help.

Code: Select all

using System; using System.Collections.Generic; using System.Linq; namespace PowerLanguage.Strategy { public class Test_X2 : SignalObject { public Test_X2(object _ctx) : base(_ctx) { sl = 3; tp = 8; bars_range = 5; range_perc = 0.25; bars_trend = 0; trend_perc1 = 0.4; trend_perc2 = 0.6; } //Market Order private IOrderMarket mkt_buy; private IOrderMarket mkt_sell; private IOrderMarket mkt_buytocover; private IOrderMarket mkt_sellshort; //Limit Orders private IOrderPriced limit_buy; private IOrderPriced limit_sell; private IOrderPriced limit_buytocover; private IOrderPriced limit_sellshort; [Input] public double sl { get; set; } [Input] public double tp { get; set; } [Input] public int bars_range { get; set; } [Input] public double range_perc { get; set; } [Input] public int bars_trend { get; set; } [Input] public double trend_perc1 { get; set; } [Input] public double trend_perc2 { get; set; } protected override void Create() { Output.Clear(); Output.WriteLine("Create Phase begonnen"); //Market Order mkt_buy = OrderCreator.MarketNextBar(new SOrderParameters(Contracts.Default, EOrderAction.Buy)); mkt_sell = OrderCreator.MarketNextBar(new SOrderParameters(Contracts.Default, EOrderAction.Sell)); mkt_buytocover = OrderCreator.MarketNextBar(new SOrderParameters(Contracts.Default, EOrderAction.BuyToCover)); mkt_sellshort = OrderCreator.MarketNextBar(new SOrderParameters(Contracts.Default, EOrderAction.SellShort)); //Limit Orders limit_buy = OrderCreator.Limit(new SOrderParameters(Contracts.Default, EOrderAction.Buy)); limit_sell = OrderCreator.Limit(new SOrderParameters(Contracts.Default, EOrderAction.Sell)); limit_buytocover = OrderCreator.Limit(new SOrderParameters(Contracts.Default, EOrderAction.BuyToCover)); limit_sellshort = OrderCreator.Limit(new SOrderParameters(Contracts.Default, EOrderAction.SellShort)); Output.WriteLine("Create Phase beendet"); } protected override void StartCalc() { Output.WriteLine("StartCalc Phase begonnen"); Output.WriteLine("StartCalc Phase beendet"); } protected override void CalcBar() { Output.WriteLine("CalcBar Phase begonnen"); Output.WriteLine("MKTBUY{0},{1}", Bars.Open[0], Bars.FullSymbolData.Current); bool Bedingung1 = Trend_Percent(Bars.Open[0], Bars.Close[bars_trend]) > trend_perc1; bool Bedingung2 = Trend_Percent(Bars.Open[0], Bars.Close[bars_trend]) < trend_perc2; bool Bedingung3 = Range_Percent(bars_trend + 1, bars_range) < range_perc; ITextObject myText = DrwText.Create( new ChartPoint(Bars.CurrentBar, Bars.Close.Value + 10), Convert.ToString(Bedingung1)); ITextObject myText2 = DrwText.Create( new ChartPoint(Bars.CurrentBar, Bars.Close.Value + 6), Convert.ToString(Bedingung2)); ITextObject myText3 = DrwText.Create( new ChartPoint(Bars.CurrentBar, Bars.Close.Value + 2), Convert.ToString(Bedingung3)); //if (Trend_Percent(Bars.Open[0], Bars.Close[bars_trend]) > trend_perc1 //&& Trend_Percent(Bars.Open[0], Bars.Close[bars_trend]) < trend_perc2 //&& Range_Percent(bars_trend + 1, bars_range) < range_perc) Output.WriteLine("Bedingungen____{0},{1},{2},{3}", Bedingung1, Bedingung2, Bedingung3, Bars.FullSymbolData.Current); if (Bedingung1 && Bedingung2 && Bedingung3) { Output.WriteLine("MKTBUY{0},{1}", Bars.Open[0], Bars.FullSymbolData.Current); mkt_buy.Send(); } if (StrategyInfo.MarketPosition != 0) { GenerateStopLoss(sl); GenerateProfitTarget(tp); } else { } Output.WriteLine("CalcBar Phase beendet"); } public double max_high; public double min_low; public double Range_Percent(int start_bar, int range_bar) { List<double> barss = new List<double>(); for (int i = start_bar; i < start_bar + range_bar; i++) { barss.Add(Bars.High[0]); barss.Add(Bars.Low[0]); } max_high = barss.Max(); min_low = barss.Min(); double range = Math.Abs(max_high - min_low); return range / max_high * 100; } public double Trend_Percent(double x, double y) { return 100 * (y - x) / x; } } }


Return to “MultiCharts .NET”