Ir para o conteúdo

Intervalos de tempo personalizados

A API de intervalo de tempo personalizado fornece tipos que permitem exibir dados OHLC personalizados de qualquer fonte, incluindo APIs de terceiros, cálculos sintéticos ou ficheiros locais, diretamente nos gráficos do cTrader. Entidades da API, como CustomTimeFrame e TimeFrameManager, permitem-lhe transmitir barras de uma fonte de dados específica e exibi-las no cTrader como um período totalmente funcional.

Os tipos importantes incluem:

  • TimeFrameManager.Custom.Add(name) para registar um novo período personalizado com um nome definido pelo utilizador.
  • CustomTimeFrame.BarsNeeded para definir como e quando os dados são carregados para o gráfico.
  • CustomBars.AppendBars(), CustomBars.UpdateLastBar(), CustomBars.PrependBars() para gerir dinamicamente a série, onde cada CustomBar contém estes seis campos: time, open, high, low, close e volume.

Uma vez adicionados, os períodos personalizados integram-se perfeitamente na interface do utilizador Período do cTrader e aparecem no menu suspenso juntamente com os períodos incorporados. Os utilizadores podem então alternar facilmente entre períodos padrão e personalizados.

Dica

Utilize períodos personalizados para visualizar mercados externos, simular tipos de barras experimentais, criar gráficos avançados de correlação/arbitragem ou realizar testes de verificação de estratégias em dados personalizados.

Os objetos da API de intervalo de tempo personalizado podem ser utilizados para fazer o seguinte:

Funcionalidade ou operação Exemplos
Exibir dados de mercado alternativos Carregar barras de APIs REST (por exemplo, AlphaVantage)
Visualizar preços de outras plataformas
Simular tipos de barras sintéticas Criar barras Heikin-Ashi, Renko ou de volume
Gerar barras a partir de índices de sentimento ou económicos
Testar dados offline Carregar barras personalizadas de um ficheiro CSV ou JSON
Realizar testes de verificação em conjuntos de dados proprietários
Sobreposições de estratégias entre ativos Traçar GBP/USD em gráficos de EUR/USD
Desenvolver modelos de arbitragem
Controlo avançado da interface do utilizador Alternar, marcar como favorito ou modificar períodos personalizados

Criar período personalizado com base em dados existentes

O plugin aqui ilustra como criar e exibir um período intradiário sintético no cTrader.

  • O plugin constrói um período de 25 minutos obtendo barras nativas de um minuto para o símbolo ativo, agregando-as em velas OHLC de 25 minutos e, em seguida, transmitindo o resultado para uma série CustomBar.
  • O novo período aparece no menu suspenso para selecionar períodos como 25Min.
  • Quando os utilizadores recuam no gráfico, o plugin carrega automaticamente mais dados de minutos, acrescenta barras mais antigas de 25 minutos e mantém a vista atualizada.
  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()
        {
        }
    }
}

Criar período personalizado usando dados externos

O plugin aqui demonstra como obter e exibir dados financeiros externos nos gráficos do cTrader usando objetos API de período personalizado.

  • O plugin cria um período personalizado no cTrader obtendo dados OHLC diários históricos para a IBM da API AlphaVantage.
  • Analisa a resposta CSV e carrega os dados numa série CustomBar, que é então exibida como um período personalizado selecionável chamado AlphaVantage na interface do gráfico.
 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
        }
    }
}