Saltar a contenido

Períodos de tiempo personalizados

La API de períodos de tiempo personalizados proporciona tipos que le permiten mostrar datos OHLC personalizados de cualquier fuente, incluidas APIs de terceros, cálculos sintéticos o archivos locales, directamente en los gráficos de cTrader. Las entidades de API, como CustomTimeFrame y TimeFrameManager, le permiten transmitir barras desde una fuente de datos específica y mostrarlas en cTrader como un período completamente desarrollado.

Los tipos importantes incluyen:

  • TimeFrameManager.Custom.Add(name) para registrar un nuevo período personalizado con un nombre definido por el usuario.
  • CustomTimeFrame.BarsNeeded para definir cómo y cuándo se cargan los datos para el gráfico.
  • CustomBars.AppendBars(), CustomBars.UpdateLastBar(), CustomBars.PrependBars() para gestionar dinámicamente la serie, donde cada CustomBar contiene estos seis campos: time, open, high, low, close y volume.

Una vez añadidos, los períodos personalizados se integran perfectamente en la interfaz de usuario Período de cTrader y aparecen en el menú desplegable junto con los períodos integrados. Los usuarios pueden entonces cambiar fácilmente entre períodos estándar y personalizados.

Consejo

Utilice períodos personalizados para visualizar mercados externos, simular tipos de barras experimentales, crear gráficos avanzados de correlación/arbitraje o hacer backtesting de estrategias con datos a medida.

Los objetos de API de períodos de tiempo personalizados se pueden utilizar para hacer lo siguiente:

Característica u operación Ejemplos
Mostrar datos de mercado alternativos Cargar barras desde APIs REST (p. ej., AlphaVantage)
Visualizar precios fuera de la plataforma
Simular tipos de barras sintéticas Crear barras Heikin-Ashi, Renko o de volumen
Generar barras a partir de índices de sentimiento o económicos
Pruebas de datos sin conexión Cargar barras personalizadas desde un archivo CSV o JSON
Hacer backtesting en conjuntos de datos propios
Superposiciones de estrategias entre activos Trazar GBP/USD en gráficos de EUR/USD
Desarrollar modelos de arbitraje
Control mejorado de la interfaz de usuario Alternar, marcar como favorito o modificar períodos personalizados

Crear período personalizado basado en datos existentes

El plugin aquí ilustra cómo crear y mostrar un período intradía sintético en cTrader.

  • El plugin construye un período de tiempo de 25 minutos obteniendo barras nativas de un minuto para el símbolo activo, agregándolas en velas OHLC de 25 minutos y luego transmitiendo el resultado a una serie CustomBar.
  • El nuevo período de tiempo aparece en el menú desplegable para seleccionar períodos de tiempo como 25Min.
  • Cuando los usuarios se desplazan hacia atrás en el gráfico, el plugin carga automáticamente más datos de minutos, antepone barras de 25 minutos más antiguas y mantiene la vista actualizada.
  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()
        {
        }
    }
}

Crear un período personalizado utilizando datos externos

El plugin aquí demuestra cómo obtener y mostrar datos financieros externos en los gráficos de cTrader utilizando objetos API de marco de tiempo personalizado.

  • El plugin crea un período personalizado en cTrader recuperando datos históricos diarios OHLC para IBM desde la API de AlphaVantage.
  • Analiza la respuesta CSV y carga los datos en una serie CustomBar, que luego se muestra como un período personalizado seleccionable llamado AlphaVantage en la interfaz de usuario del 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
        }
    }
}