콘텐츠로 이동

사용자 정의 시간 프레임

사용자 정의 시간 프레임 API는 타사 API, 합성 계산 또는 로컬 파일을 포함한 모든 소스에서 사용자 정의 OHLC 데이터를 cTrader 차트에 직접 표시할 수 있는 유형을 제공합니다. CustomTimeFrameTimeFrameManager와 같은 API 엔티티를 사용하면 특정 데이터 소스에서 바를 스트리밍하고 cTrader에서 완전한 기간으로 표시할 수 있습니다.

중요한 유형에는 다음이 포함됩니다:

  • TimeFrameManager.Custom.Add(name)를 사용하여 사용자 정의 이름으로 새로운 사용자 정의 기간을 등록합니다.
  • CustomTimeFrame.BarsNeeded를 사용하여 차트에 대한 데이터가 로드되는 방식과 시기를 정의합니다.
  • CustomBars.AppendBars(), CustomBars.UpdateLastBar(), CustomBars.PrependBars()를 사용하여 시리즈를 동적으로 관리하며, 각 CustomBartime, open, high, low, closevolume을 보유합니다.

일단 추가되면 사용자 정의 기간은 cTrader 기간 UI에 원활하게 통합되고 내장 기간과 함께 드롭다운에 나타납니다. 사용자는 표준 기간과 사용자 정의 기간 간에 쉽게 전환할 수 있습니다.

사용자 정의 기간을 사용하여 외부 시장을 시각화하거나 실험적 바 유형을 시뮬레이션하거나 고급 상관관계/차익 차트를 생성하거나 맞춤 데이터에서 전략을 백테스트하세요.

사용자 정의 시간 프레임 API 객체를 사용하여 다음을 수행할 수 있습니다:

기능 또는 작업 예시
대체 시장 데이터 표시 REST API(예: AlphaVantage)에서 바를 로드
플랫폼 외부 가격 시각화
합성 바 유형 시뮬레이션 하이킨 아시, 렌코 또는 거래량 바 생성
감정 또는 경제 지수에서 바 생성
오프라인 데이터 테스트 CSV 또는 JSON 파일에서 맞춤형 바 로드
독점 데이터셋에서 백테스트
크로스 자산 전략 오버레이 EUR/USD 차트에 GBP/USD 플로팅
차익 거래 모델 개발
향상된 UI 제어 맞춤형 기간 토글, 즐겨찾기 또는 수정

기존 데이터를 기반으로 맞춤형 기간 생성

여기 플러그인은 cTrader에서 합성 인트라데이 기간을 생성하고 표시하는 방법을 보여줍니다.

  • 플러그인은 활성 심볼에 대한 기본 1분 바를 가져와서 25분 OHLC 캔들로 집계한 다음 결과를 CustomBar 시리즈로 스트리밍하여 25분 시간 프레임을 구축합니다.
  • 새로운 시간 프레임은 25Min으로 시간 프레임 선택 드롭다운 메뉴에 나타납니다.
  • 사용자가 차트를 스크롤하면 플러그인은 자동으로 더 많은 분 데이터를 로드하고 이전 25분 바를 앞에 추가하여 뷰를 최신 상태로 유지합니다.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
using System;
using System.Linq;                 
using cAlgo.API;
using cAlgo.API.Internals;

namespace cAlgo.Plugins
{
    [Plugin(AccessRights = AccessRights.None)]
    public class TF25 : Plugin
    {
        private CustomTimeFrame _tf25Min;
        private bool _isLoadMoreEnabled = true;

        protected override void OnStart()
        {
            // Create the 25-minute TF
            _tf25Min = TimeFrameManager.Custom.Add("25Min");
            _tf25Min.Description = "25‑minute aggregated from 1‑minute bars";

            // Hook initial load and on‑scroll‑back
            _tf25Min.NewChart += OnNewChart;
            _tf25Min.BarsNeeded = OnBarsNeeded;
        }

        private void OnNewChart(CustomTimeFrameNewChartEventArgs args)
        {
            var cb    = args.CustomBars;
            var chart = args.Chart;

            // Show a loading indicator
            var loading = new TextBlock { Text = "Loading 25‑min bars…", FontSize = 12 };
            chart.AddControl(loading);

            // Fetch the 1‑min bars and aggregate
            MarketData.GetBarsAsync(TimeFrame.Minute, cb.Symbol.Name, minuteBars =>
            {
                var aggregated = minuteBars
                    .Select((bar, idx) => new { bar, idx })
                    .GroupBy(x => x.idx / 25)
                    .Select(g =>
                    {
                        var first = g.First().bar;
                        var last  = g.Last().bar;
                        return new CustomBar(
                            time:        first.OpenTime,
                            open:        first.Open,
                            high:        g.Max(x => x.bar.High),
                            low:         g.Min(x => x.bar.Low),
                            close:       last.Close,
                            volume:  g.Sum(x => (int)x.bar.TickVolume)
                        );
                    });

                chart.RemoveControl(loading);


            });
        }

        private void OnBarsNeeded(CustomTimeFrameBarsNeededArgs args)
        {
            var cb = args.CustomBars;

            // Same logic for explicit BarsNeeded triggers
            MarketData.GetBarsAsync(TimeFrame.Minute, cb.Symbol.Name, minuteBars =>
            {
                var aggregated = minuteBars
                    .Select((bar, idx) => new { bar, idx })
                    .GroupBy(x => x.idx / 25)
                    .Select(g => new CustomBar(
                        time:        g.First().bar.OpenTime,
                        open:        g.First().bar.Open,
                        high:        g.Max(x => x.bar.High),
                        low:         g.Min(x => x.bar.Low),
                        close:       g.Last().bar.Close,
                        volume:  g.Sum(x => (int)x.bar.TickVolume)
                    ));
                cb.AppendBars(aggregated);
                 args.CustomBars.NeedsMore += _ =>
                {
                    if (!_isLoadMoreEnabled)
                    {
                        Print("Load‑more disabled; skipping additional bars.");
                        return;
                    }

                    Print("NeedsMore fired; loading more history…");
                    minuteBars.LoadMoreHistoryAsync(loadArgs =>
                    {
                        Print($"Loaded {loadArgs.Count} more 1‑min bars");
                        if (loadArgs.Count == 0)
                            return;

                        Sleep(TimeSpan.FromSeconds(1));
                        args.CustomBars.PrependBars(minuteBars.Take(loadArgs.Count).Select(bar => new CustomBar(bar.OpenTime, bar.Open, bar.High, bar.Low, bar.Close, (int)bar.TickVolume)));
                    });
                };
            });
        }

        protected override void OnStop()
        {
        }
    }
}

외부 데이터를 사용하여 맞춤형 기간 생성

여기 플러그인은 맞춤형 시간 프레임 API 객체를 사용하여 cTrader 차트에 외부 금융 데이터를 가져와 표시하는 방법을 보여줍니다.

  • 플러그인은 AlphaVantage API에서 IBM의 과거 일일 OHLC 데이터를 검색하여 cTrader에서 맞춤형 기간을 생성합니다.
  • CSV 응답을 파싱하고 데이터를 CustomBar 시리즈에 로드한 다음, 차트 UI에서 AlphaVantage라는 선택 가능한 맞춤형 기간으로 표시합니다.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
using System;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Plugins
{
    [Plugin(AccessRights = AccessRights.None)]
    public class CustomTimeFrameAlphaVantage : Plugin
    {
        private const string ApiKey = "YOUR_ALPHA_VANTAGE_KEY";
        private const string Symbol = "IBM";
        private const string Endpoint = $"https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol={Symbol}&apikey={ApiKey}&datatype=csv&outputsize=full";

        private CustomTimeFrame _customTimeFrame;

        protected override void OnStart()
        {
            _customTimeFrame = TimeFrameManager.Custom.Add("AlphaVantage");

            _customTimeFrame.Description = "Loads data from AlphaVantage";

            _customTimeFrame.BarsNeeded = args => 
            {
                var response = Http.Get(new Uri(Endpoint));

                if (!response.IsSuccessful)
                {
                    Print($"Error loading data from AlphaVantage, status code: {response.StatusCode}, body: {response.Body}");
                    return;
                }

                Print($"Response Received: {response.StatusCode}");

                var ohlcData = response.Body.Split(Environment.NewLine)[1..];

                Array.Reverse(ohlcData);

                Print($"ohlcData Count: {ohlcData.Length}");

                var bars = new List<CustomBar>();

                foreach (var ohlc in ohlcData)
                {
                    var ohlcSplit = ohlc.Split(',');

                    if (ohlcSplit.Length < 6) continue;

                    var time = DateTime.Parse(ohlcSplit[0]);
                    var open = double.Parse(ohlcSplit[1]);
                    var high = double.Parse(ohlcSplit[2]);
                    var low = double.Parse(ohlcSplit[3]);
                    var close = double.Parse(ohlcSplit[4]);
                    var volume = long.Parse(ohlcSplit[5]);

                    bars.Add(new CustomBar(time, open, high, low, close, volume));
                }

                Print($"AppendBars Count: {bars.Count}");

                args.CustomBars.AppendBars(bars);
            };
        }

        protected override void OnStop()
        {
            // Handle Plugin stop here
        }
    }
}