Lewati ke isi

Kerangka waktu kustom

API kerangka waktu kustom menyediakan tipe yang memungkinkan Anda untuk menampilkan data OHLC kustom dari sumber mana pun, termasuk API pihak ketiga, perhitungan sintetis atau file lokal, langsung di grafik cTrader. Entitas API, seperti CustomTimeFrame dan TimeFrameManager, memungkinkan Anda untuk mengalirkan bar dari sumber data tertentu dan menampilkannya di cTrader sebagai periode yang sepenuhnya berfungsi.

Tipe penting meliputi:

  • TimeFrameManager.Custom.Add(name) untuk mendaftarkan periode kustom baru dengan nama yang ditentukan pengguna.
  • CustomTimeFrame.BarsNeeded untuk menentukan bagaimana dan kapan data dimuat untuk grafik.
  • CustomBars.AppendBars(), CustomBars.UpdateLastBar(), CustomBars.PrependBars() untuk mengelola rangkaian secara dinamis, di mana setiap CustomBar memiliki enam bidang ini: time, open, high, low, close dan volume.

Setelah ditambahkan, periode kustom terintegrasi dengan mulus ke dalam UI Period cTrader dan muncul dalam dropdown bersama periode bawaan. Pengguna kemudian dapat dengan mudah beralih antara periode standar dan kustom.

Tips

Gunakan periode kustom untuk memvisualisasikan pasar eksternal, mensimulasikan tipe bar eksperimental, membuat grafik korelasi/arbitrase lanjutan atau melakukan backtesting strategi pada data yang disesuaikan.

Objek API kerangka waktu kustom dapat digunakan untuk melakukan hal-hal berikut:

Fitur atau operasi Contoh
Menampilkan data pasar alternatif Memuat bar dari REST API (mis. AlphaVantage)
Memvisualisasikan harga di luar platform
Mensimulasikan tipe bar sintetis Membuat bar Heikin-Ashi, Renko atau volume
Menghasilkan bar dari sentimen atau indeks ekonomi
Pengujian data offline Memuat bar kustom dari file CSV atau JSON
Melakukan backtesting pada dataset eksklusif
Overlay strategi lintas aset Memplot GBP/USD pada grafik EUR/USD
Mengembangkan model arbitrase
Kontrol UI yang ditingkatkan Mengaktifkan/menonaktifkan, memfavoritkan atau memodifikasi periode kustom

Membuat periode kustom berdasarkan data yang ada

Plugin di sini mengilustrasikan cara membuat dan menampilkan periode intraday sintetis di cTrader.

  • Plugin ini membangun kerangka waktu 25 menit dengan mengambil bar satu menit asli untuk simbol aktif, menggabungkannya menjadi lilin OHLC 25 menit dan kemudian mengalirkan hasilnya ke dalam rangkaian CustomBar.
  • Kerangka waktu baru muncul dalam menu drop-down untuk memilih kerangka waktu sebagai 25Min.
  • Ketika pengguna menggulir ke belakang pada grafik, plugin secara otomatis memuat lebih banyak data menit, menambahkan bar 25 menit yang lebih lama di awal dan menjaga tampilan tetap up to date.
  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()
        {
        }
    }
}

Membuat periode kustom menggunakan data eksternal

Plugin di sini mendemonstrasikan cara mengambil dan menampilkan data keuangan eksternal di grafik cTrader menggunakan objek API kerangka waktu kustom.

  • Plugin ini membuat periode kustom di cTrader dengan mengambil data OHLC harian historis untuk IBM dari API AlphaVantage.
  • Ini mengurai respons CSV dan memuat data ke dalam rangkaian CustomBar, yang kemudian ditampilkan sebagai periode kustom yang dapat dipilih bernama AlphaVantage di UI grafik.
 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
        }
    }
}