出于学习目的,我正在 ctrader 中编写自定义指标。它应该每 20 个柱在 5 个柱上绘制一条趋势线。但当它绘制新的趋势线时,前一条趋势线就会消失。你能帮我吗?
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
{
[Indicator(AccessRights = AccessRights.None)]
public class testdrawline : Indicator
{
[Output("Main")]
public IndicatorDataSeries Result { get; set; }
int period = 20;
protected override void Initialize()
{
}
public override void Calculate(int index)
{
// here calculate the bars. when it reached the 20. bar then draw the line
if (index < period)return;
if (index - 20 == period) period += 20;
var l = Chart.DrawTrendLine("line", Bars[index].OpenTime, Bars[index].Close, Bars[index - 5].OpenTime, Bars[index - 5].Close, "Yellow");
l.IsInteractive = true;
}
}
}
您的代码实际上有两个问题。正如 Cleptus 提到的,您的条件
if (index - 20 == period)
无法有效捕获 20 小节周期。
Cleptus 已经给出了一个解决方案来修复您的 20 条循环逻辑,但为了完整起见,我将在这篇文章中解决这两个问题。
20 条循环逻辑:
您可以按原样使用 Ceptus 提供的解决方案。您还可以对此进行扩展,通过执行类似
if ((index % 20 == 0) && (index >= 5))
的操作来使条件更加稳健。其中 index>=5
与 index % 20 == 0
相连,以确保在前 4 个柱期间,您的代码不会尝试访问负柱索引。
持久图表绘制对象:
现在解决您的主要问题。在这种情况下,为了确保图表绘图对象保持持久性,您所需要做的就是为每个绘图对象指定一个唯一的名称。在原始代码中,您使用相同的名称命名所有要绘制的趋势线,即
"line"
。在 cTrader Automate API 中,绘图对象通过其名称进行标识,因此,如果您创建一个名为 "line"
的绘图对象,然后更改其坐标,它将在新坐标的位置重新绘制同一对象,这就是您需要解决的问题似乎正在经历。
要解决这个问题,只需确保您要绘制的每条趋势线都有唯一的名称即可。有很多方法可以做到这一点。最简单的方法是创建一个线索引变量,并在每次绘制新趋势线时简单地增加它。然后使用该递增索引为新趋势线编译一个唯一的名称,类似于
string lineName = "line_" + index;
示例解决方案:
这里是一个示例,说明如何更新代码,以解决柱形循环逻辑并确保图表绘制对象持久性。
using System.Linq;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
namespace cAlgo
{
[Indicator(AccessRights = AccessRights.None)]
public class testdrawline : Indicator
{
[Output("Main")]
public IndicatorDataSeries Result { get; set; }
private int trendlinePeriod = 5;
private int trendlineGap = 20;
private string trendlineName = "line";
protected override void Initialize()
{
}
public override void Calculate(int index)
{
// Draw a line every 20 bars.
// - We conjoin the condition `index >= 5` to prevent attempts to access negative indexes at the beginning of the bar range.
if ((index % trendlineGap == 0) && (index >= trendlinePeriod))
{
// Compile a new object name for the new trend-line by concatenating the object name with the bar index.
// - Using a unique object name will ensure that we don't affect any previously drawn objects.
// - Note, we can use any unique index we like here. We are just using the bar index for the sake of convenience.
string objectName = $"{trendline_name}_{index}";
// Draw a new trend-line, using the newly compiled object name.
var l = Chart.DrawTrendLine(objectName, Bars[index].OpenTime, Bars[index].Close, Bars[index - trendlinePeriod].OpenTime, Bars[index - trendlinePeriod].Close, "Yellow");
l.IsInteractive = true;
}
}
}
}