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;
}
Sending an order not at the bar 0
-
- Posts: 87
- Joined: 10 Feb 2022
- Has thanked: 53 times
- Been thanked: 11 times
Re: Sending an order not at the bar 0
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:
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.
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);
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.
Re: Sending an order not at the bar 0
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;
}
}
}
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
-
- Posts: 87
- Joined: 10 Feb 2022
- Has thanked: 53 times
- Been thanked: 11 times
Re: Sending an order not at the bar 0
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:
to
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.
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;
}
}
}