ctrader 中的自定义指标无法绘制多条趋势线

问题描述 投票:0回答:1

出于学习目的,我正在 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;
        }
    }
}
c# indicator
1个回答
0
投票

您的代码实际上有两个问题。正如 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;
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.