Skip to content

CustomTimeFrames

interface cAlgo.API Since 5.3

DesktopCLICloud

Represents collection of custom time frames.

Environment behaviour

CLI — not supported. Available to plugins only, and plugins cannot run in the CLI.

Cloud — not supported. Available to plugins only, and plugins cannot run in the cloud.

Definition

public interface CustomTimeFrames

Namespace: cAlgo.API · Group: Custom

Examples

using System;
using cAlgo.API;
using cAlgo.API.Internals;
using System.Linq;

namespace cAlgo.Plugins;

public partial class CustomTimeFrameTest : Plugin
{
    private const string InitialDescription = "This is custom time frame initial description";
    private const string ChangedDescription = "This is custom time frame changed description";

    private bool _isLoadMoreEnabled = true;

    private CustomTimeFrame _customTimeFrame;
    private CustomBars _customBars;

    protected override void OnStart()
    {
        var panel = new StackPanel();

        var addCustomTimeFrameButton = new Button { Text = "Add Custom Time Frame" };

        addCustomTimeFrameButton.Click += OnAddCustomTimeFrameButtonClick;

        panel.AddChild(addCustomTimeFrameButton);

        var removeCustomTimeFrameButton = new Button { Text = "Remove Custom Time Frame" };

        removeCustomTimeFrameButton.Click += OnRemoveCustomTimeFrameButtonClick;

        panel.AddChild(removeCustomTimeFrameButton);

        var displayChartInfoButton = new Button { Text = "Display Charts Info" };

        displayChartInfoButton.Click += OnDisplayChartInfoButtonClick;

        panel.AddChild(displayChartInfoButton);

        var changeDescriptionButton = new Button { Text = "Change Description" };

        changeDescriptionButton.Click += OnChangeDescriptionButtonClick;

        panel.AddChild(changeDescriptionButton);

        var pauseOrResumeLoadMoreButton = new Button { Text = "Pause / Resume Load More" };
        pauseOrResumeLoadMoreButton.Click += OnPauseOrResumeLoadMoreButtonClick;

        panel.AddChild(pauseOrResumeLoadMoreButton);

        var showRegularBarsInfoButton = new Button { Text = "Show Regular Bars Info" };
        showRegularBarsInfoButton.Click += OnShowRegularBarsInfoButtonClick;

        panel.AddChild(showRegularBarsInfoButton);

        var addBarsButton = new Button { Text = "Add Bars For Active Chart Symbol" };
        addBarsButton.Click += OnAddBarsButtonClick;

        panel.AddChild(addBarsButton);

        var removeBarsButton = new Button { Text = "Remove Bars For Active Chart Symbol" };
        removeBarsButton.Click += OnRemoveBarsButtonClick;

        panel.AddChild(removeBarsButton);

        var updateLastBarButton = new Button { Text = "Update Last Bar" };
        updateLastBarButton.Click += OnUpdateLastBarButtonClick;

        panel.AddChild(updateLastBarButton);

        var block = Asp.SymbolTab.AddBlock("Custom Time Frame Test");

        block.Child = panel;

        ChartManager.FramesAdded += OnChartManagerFramesAdded;

        TimeFrames.Added += OnTimeFramesAdded;
        TimeFrames.Removed += OnTimeFramesRemoved;
    }

    private void OnTimeFramesRemoved(TimeFramesRemovedEventArgs args)
    {
        Print($"TimeFrames Removed: {string.Join(", ", args.TimeFrames.Select(tf => tf.Name))}");
    }

    private void OnTimeFramesAdded(TimeFramesAddedEventArgs args)
    {
        Print($"TimeFrames Added: {string.Join(", ", args.TimeFrames.Select(tf => tf.Name))}");
    }

    private void OnChartManagerFramesAdded(FramesAddedEventArgs obj)
    {
        if (obj.AddedFrames[0] is not ChartFrame chartFrame)
            return;

        Print($"New chart frame added, {chartFrame.Symbol.Name} {chartFrame.TimeFrame.Name}");
    }

    private void OnUpdateLastBarButtonClick(ButtonClickEventArgs obj)
    {
        var changeAmount = (_customBars.Bars.LastBar.High - _customBars.Bars.LastBar.Low) * (Random.Shared.NextDouble() + 0.5) * 2;

        Print($"Chaning Last Bar: {_customBars.Bars.LastBar} | change: {changeAmount}");

        _customBars.UpdateLastBar(_customBars.Bars.LastBar.Open, _customBars.Bars.LastBar.Open + changeAmount, _customBars.Bars.LastBar.Open - changeAmount, _customBars.Bars.LastBar.Close + changeAmount, (int)_customBars.Bars.LastBar.TickVolume + 1);
    }

    private void OnRemoveCustomTimeFrameButtonClick(ButtonClickEventArgs obj)
    {
        TimeFrameManager.Custom.Remove(_customTimeFrame);

        Print($"Custom Time frame '{_customTimeFrame.Name}' has been removed.");
    }

    private void OnDisplayChartInfoButtonClick(ButtonClickEventArgs obj)
    {
        DisplayChartsInfo();
    }

    private void OnChangeDescriptionButtonClick(ButtonClickEventArgs obj)
    {
        _customTimeFrame.Description = _customTimeFrame.Description == InitialDescription ? ChangedDescription : InitialDescription;

        Print($"Changed description to: {_customTimeFrame.Description}");
    }

    private void OnPauseOrResumeLoadMoreButtonClick(ButtonClickEventArgs obj)
    {
        _isLoadMoreEnabled = !_isLoadMoreEnabled;
    }

    private void OnAddBarsButtonClick(ButtonClickEventArgs obj)
    {
        if (ChartManager.ActiveFrame is not ChartFrame { Chart: var chart })
            return;

        var bars = _customTimeFrame.AddBars(chart.Symbol);

        Print($"Added Bars, Count: {bars.Bars.Count}, Get: {bars == _customTimeFrame.GetBars(chart.Symbol)}");
    }

    private void OnRemoveBarsButtonClick(ButtonClickEventArgs obj)
    {
        if (ChartManager.ActiveFrame is not ChartFrame { Chart: var chart })
            return;

        var result = _customTimeFrame.RemoveBars(chart.Symbol);

        Print($"Removed Bars, Result: {result}, Get is null: {_customTimeFrame.GetBars(chart.Symbol) == null}");
    }

    private void OnShowRegularBarsInfoButtonClick(ButtonClickEventArgs obj)
    {
        Print($"Regular Bars, Count: {_customBars.Bars.Count}, LastBar: {_customBars.Bars.LastBar}, FirstBar: {_customBars.Bars[0]}");
    }

    private void OnAddCustomTimeFrameButtonClick(ButtonClickEventArgs obj)
    {
        _customTimeFrame = TimeFrameManager.Custom.Add("Test");

        _customTimeFrame.Description = InitialDescription;
        _customTimeFrame.BarsNeeded = OnCustomTimeFrameBarsNeeded;

        Print($"Custom Time frame '{_customTimeFrame.Name}' has been added.");

        DisplayChartsInfo();
    }

    private void DisplayChartsInfo()
    {
        foreach (var frame in ChartManager)
        {
            if (frame is not ChartFrame chartFrame)
                continue;

            Print($"Chart, {chartFrame.Symbol.Name} {chartFrame.TimeFrame.Name}");
        }
    }

    private void OnCustomTimeFrameBarsNeeded(CustomTimeFrameBarsNeededArgs args)
    {
        Print($"Bars Needed for custom time frame, Symbol: {args.CustomBars.Symbol}, Name: {args.CustomTimeFrame.Name}");

        _customBars = args.CustomBars;

        MarketData.GetBarsAsync(TimeFrame.Daily, args.CustomBars.Symbol.Name, bars =>
        {
            Print($"Bars Loaded: {bars.Count}");

            Sleep(TimeSpan.FromSeconds(5));

            args.CustomBars.AppendBars(bars.Select(bar => new CustomBar(bar.OpenTime, bar.Open, bar.High, bar.Low, bar.Close, (int)bar.TickVolume)));

            args.CustomBars.NeedsMore += _ =>
            {
                if (!_isLoadMoreEnabled)
                {
                    Print("Needs more requested but load more is disabled");
                    return;
                }

                Print($"Bars NeedsMore");

                bars.LoadMoreHistoryAsync(loadedMoreArgs =>
                {
                    Print($"Bars Loaded more: {loadedMoreArgs.Count}");

                    if (loadedMoreArgs.Count == 0)
                        return;

                    Sleep(TimeSpan.FromSeconds(5));
                    args.CustomBars.PrependBars(bars.Take(loadedMoreArgs.Count).Select(bar => new CustomBar(bar.OpenTime, bar.Open, bar.High, bar.Low, bar.Close, (int)bar.TickVolume)));
                });
            };
        });
    }
}
import clr
clr.AddReference("cAlgo.API")

from cAlgo.API import *
from System import Action, TimeSpan, Array, DayOfWeek
import random

class Test():
    InitialDescription = "This is custom time frame initial description"
    ChangedDescription = "This is custom time frame changed description"

    def on_start(self):
        self.isLoadMoreEnabled = True
        self.customTimeFrame = None

        panel = StackPanel()

        addCustomTimeFrameButton = Button()
        addCustomTimeFrameButton.Text = "Add Custom TimeFrame"
        addCustomTimeFrameButton.Click += self.on_add_custom_time_frame_button_click

        panel.AddChild(addCustomTimeFrameButton)

        removeCustomTimeFrameButton = Button()
        removeCustomTimeFrameButton.Text = "Remove Custom TimeFrame"
        removeCustomTimeFrameButton.Click += self.on_remove_custom_time_frame_button_click

        panel.AddChild(removeCustomTimeFrameButton)

        displayChartInfoButton = Button()
        displayChartInfoButton.Text = "Display Charts Info"
        displayChartInfoButton.Click += self.on_display_chart_info_button_click

        panel.AddChild(displayChartInfoButton)

        changeDescriptionButton = Button()
        changeDescriptionButton.Text = "Change Description"
        changeDescriptionButton.Click += self.on_change_description_button_click

        panel.AddChild(changeDescriptionButton)

        pauseOrResumeLoadMoreButton = Button()
        pauseOrResumeLoadMoreButton.Text = "Pause / Resume Load More"
        pauseOrResumeLoadMoreButton.Click += self.on_pause_or_resume_load_more_button_click

        panel.AddChild(pauseOrResumeLoadMoreButton)

        showRegularBarsInfoButton = Button()
        showRegularBarsInfoButton.Text = "Show Regular Bars Info"
        showRegularBarsInfoButton.Click += self.on_show_regular_bars_info_button_click

        panel.AddChild(showRegularBarsInfoButton)

        addBarsButton = Button()
        addBarsButton.Text = "Add Bars For Active Chart Symbol"
        addBarsButton.Click += self.on_add_bars_button_click

        panel.AddChild(addBarsButton)

        removeBarsButton = Button()
        removeBarsButton.Text = "Remove Bars For Active Chart Symbol"
        removeBarsButton.Click += self.on_remove_bars_button_click

        panel.AddChild(removeBarsButton)

        updateLastBarButton = Button()
        updateLastBarButton.Text = "Update Last Bar"
        updateLastBarButton.Click += self.on_update_last_bar_button_click

        panel.AddChild(updateLastBarButton)

        block = api.Asp.SymbolTab.AddBlock("Custom TimeFrame Test")
        block.Child = panel
        block.Height = 550

        api.ChartManager.FramesAdded += self.on_chart_manager_frames_addded

        api.TimeFrames.Added += self.on_time_frames_added
        api.TimeFrames.Removed += self.on_time_frames_removed

    def on_add_custom_time_frame_button_click(self, args):
        self.customTimeFrame = api.TimeFrameManager.Custom.Add("Test")
        self.customTimeFrame.Description = self.InitialDescription
        self.customTimeFrame.BarsNeeded = Action[CustomTimeFrameBarsNeededArgs](self.on_custom_time_frame_bars_needed)

        print(f"custom TimeFrame '{self.customTimeFrame.Name}' has been added.")

    def on_custom_time_frame_bars_needed(self, args):
        print(f"Bars Needed for custom TimeFrame, Symbol: {args.CustomBars.Symbol}, Name: {args.CustomTimeFrame.Name}")

        self.customBars = args.CustomBars

        api.MarketData.GetBarsAsync(TimeFrame.Daily, args.CustomBars.Symbol.Name, Action[Bars](self.on_bars_received))

    def on_bars_received(self, bars):
        print(f"Bars Loaded: {bars.Count}")

        api.Sleep(2000)

        self.customBars.AppendBars(self.to_array([CustomBar(bar.OpenTime, bar.Open, bar.High, bar.Low, bar.Close, int(bar.TickVolume)) for bar in bars], CustomBar))
        self.customBars.NeedsMore += lambda args: self.on_custom_bars_needs_more(bars, args.CustomBars)

        bars.BarOpened += lambda args: self.on_bar_opened(self.customBars, args.Bars)
        bars.Tick += lambda args: self.on_tick(self.customBars, args.Bars)

    def on_custom_bars_needs_more(self, bars, customBars):
        if self.isLoadMoreEnabled is False:
            print("Needs more requested but load more is disabled")
            return

        print("Bars NeedsMore")

        bars.LoadMoreHistoryAsync(Action[BarsHistoryLoadedEventArgs](lambda args: self.on_bars_more_history_loaded(customBars, bars, args.Count)))

    def on_bars_more_history_loaded(self, customBars, bars, loadedCount):
        print(f"Bars Loaded more: {loadedCount}")

        if loadedCount == 0:
            return

        api.Sleep(2000)

        loadedBars = []

        for i, bar in enumerate(bars):
            if i >= loadedCount:
                break
            loadedBars.append(CustomBar(bar.OpenTime, bar.Open, bar.High, bar.Low, bar.Close, int(bar.TickVolume)))

        customBars.PrependBars(self.to_array(loadedBars, CustomBar))

    def on_bar_opened(self, customBars, bars):
        if self.customTimeFrame is None:
            return

        customBars.AppendBar(CustomBar(bars.LastBar.OpenTime, bars.LastBar.Open, bars.LastBar.High, bars.LastBar.Low, bars.LastBar.Close, bars.LastBar.TickVolume))

    def on_tick(self, customBars, bars):
        if self.customTimeFrame is None:
            return

        customBars.UpdateLastBar(bars.LastBar.Open, bars.LastBar.High, bars.LastBar.Low, bars.LastBar.Close, bars.LastBar.TickVolume)

    def on_remove_custom_time_frame_button_click(self, args):
        if api.TimeFrameManager.Custom.Remove(self.customTimeFrame) == False:
            return

        print(f"custom TimeFrame '{self.customTimeFrame.Name}' has been removed.")
        self.customTimeFrame = None

    def on_display_chart_info_button_click(self, args):
        for frame in api.ChartManager:
            if isinstance(frame.__implementation__, ChartFrame) == False:
                continue

            chartFrame = ChartFrame(frame)
            print(f"Chart, {chartFrame.Symbol.Name} {chartFrame.TimeFrame.Name}")

    def on_change_description_button_click(self, args):
        self.customTimeFrame.Description = self.ChangedDescription if self.customTimeFrame.Description == self.InitialDescription else self.InitialDescription
        print(f"Changed description to: {self.customTimeFrame.Description}")

    def to_array(self, iterable, itemType):
        length = len(iterable)
        array = Array[itemType](length)
        for i in range(length):
            array[i] = iterable[i]

        return array

    def on_pause_or_resume_load_more_button_click(self, args):
        self.isLoadMoreEnabled = not self.isLoadMoreEnabled

    def on_show_regular_bars_info_button_click(self, args):
        print(f"Regular Bars, Count: {self.customBars.Bars.Count}, LastBar: {self.customBars.Bars.LastBar}, FirstBar: {self.customBars.Bars[0]}")

    def on_add_bars_button_click(self, args):
        if isinstance(api.ChartManager.ActiveFrame.__implementation__, ChartFrame) == False:
            return
        chart = ChartFrame(api.ChartManager.ActiveFrame).Chart
        bars = self.customTimeFrame.AddBars(chart.Symbol)
        print(f"Added Bars, Count: {bars.Bars.Count}, Get: {bars == self.customTimeFrame.GetBars(chart.Symbol)}")

    def on_remove_bars_button_click(self, args):
        if isinstance(api.ChartManager.ActiveFrame.__implementation__, ChartFrame) == False:
            return
        chart = ChartFrame(api.ChartManager.ActiveFrame).Chart
        result = self.customTimeFrame.RemoveBars(chart.Symbol)
        print(f"Removed Bars, Result: {result}, Get is None: {self.customTimeFrame.GetBars(chart.Symbol) is None}")

    def on_update_last_bar_button_click(self, args):
        changeAmount = (self.customBars.Bars.LastBar.High - self.customBars.Bars.LastBar.Low) * (random.random() + 0.5) * 2
        print(f"Changing Last Bar: {self.customBars.Bars.LastBar} | change: {changeAmount}")
        bars = self.customBars.Bars
        self.customBars.UpdateLastBar(bars.LastBar.Open, bars.LastBar.Open + changeAmount, bars.LastBar.Open - changeAmount, bars.LastBar.Close + changeAmount, int(bars.LastBar.TickVolume + 1))

    def on_chart_manager_frames_addded(self, args):
        for frame in args.AddedFrames:
            if isinstance(frame.__implementation__, ChartFrame) == False:
                continue
            chartFrame = ChartFrame(frame)
            print(f"New chart frame added, {chartFrame.Symbol.Name} {chartFrame.TimeFrame.Name}")

    def on_time_frames_added(self, args):
        print(f"TimeFrames Added: {', '.join([tf.Name for tf in args.TimeFrames])}")

    def on_time_frames_removed(self, args):
        print(f"TimeFrames Removed: {', '.join([tf.Name for tf in args.TimeFrames])}")
{
  "AccessRights": "None"
}

Methods

Name Description
AddDesktopCLICloudCustomTimeFrame Adds a new custom time frame.
GetDesktopCLICloudCustomTimeFrame Returns a custom time frame by it's name.
RemoveDesktopCLICloudbool Removes a custom time frame.

See also