Skip to content

CustomSymbols

interface cAlgo.API Since 5.3

DesktopCLICloud

Represents collection of custom symbols.

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 CustomSymbols

Namespace: cAlgo.API · Group: Custom

Examples

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

namespace cAlgo.Plugins;

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

    private bool _isLoadMoreEnabled = true;

    private CustomSymbol _customSymbol;
    private CustomBars _customBars;

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

        var addCustomSymbolWithBaseButton = new Button { Text = "Add custom symbol with Base Symbol" };

        addCustomSymbolWithBaseButton.Click += OnAddCustomSymbolWithBaseButtonClick;

        panel.AddChild(addCustomSymbolWithBaseButton);

        var addCustomSymbolWithoutBaseButton = new Button { Text = "Add custom symbol without Base Symbol" };

        addCustomSymbolWithoutBaseButton.Click += OnAddCustomSymbolWithoutBaseButtonClick;

        panel.AddChild(addCustomSymbolWithoutBaseButton);

        var removeCustomSymbolButton = new Button { Text = "Remove custom symbol" };

        removeCustomSymbolButton.Click += OnRemoveCustomSymbolButtonClick;

        panel.AddChild(removeCustomSymbolButton);

        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 updateSymbolPropertiesButton = new Button { Text = "Update Symbol Properties" };

        updateSymbolPropertiesButton.Click += OnUpdateSymbolPropertiesButtonClick;

        panel.AddChild(updateSymbolPropertiesButton);

        var updateSymbolBaseAssetButton = new Button { Text = "Update Symbol Base Asset" };

        updateSymbolBaseAssetButton.Click += OnUpdateSymbolBaseAssetButtonClick;

        panel.AddChild(updateSymbolBaseAssetButton);

        var updateSymbolQuoteAssetButton = new Button { Text = "Update Symbol Quote Asset" };

        updateSymbolQuoteAssetButton.Click += OnUpdateSymbolQuoteAssetButtonClick;

        panel.AddChild(updateSymbolQuoteAssetButton);

        var showSymbolPropertiesButton = new Button { Text = "Show Symbol Properties" };

        showSymbolPropertiesButton.Click += args => ShowSymbolProperties();

        panel.AddChild(showSymbolPropertiesButton);

        var showSymbolAssetsButton = new Button { Text = "Show Symbol Assets" };

        showSymbolAssetsButton.Click += args => ShowSymbolAssets();

        panel.AddChild(showSymbolAssetsButton);

        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 updateSymbolSentimentButton = new Button { Text = "Update Symbol Sentiment" };

        updateSymbolSentimentButton.Click += OnUpdateSymbolSentimentButtonClick;

        panel.AddChild(updateSymbolSentimentButton);

        var showSymbolSentimentButton = new Button { Text = "Show Symbol Sentiment" };

        showSymbolSentimentButton.Click += _ => ShowSymbolSentiment();

        panel.AddChild(showSymbolSentimentButton);

        var updateSymbolDynamicLeverageButton = new Button { Text = "Update Symbol Dynamic Leverage" };

        updateSymbolDynamicLeverageButton.Click += OnUpdateSymbolDynamicLeverageButtonClick;

        panel.AddChild(updateSymbolDynamicLeverageButton);

        var showSymbolDynamicLeverageButton = new Button { Text = "Show Symbol Dynamic Leverage" };

        showSymbolDynamicLeverageButton.Click += _ => ShowSymbolDynamicLeverage();

        panel.AddChild(showSymbolDynamicLeverageButton);

        var updateSymbolHolidaysButton = new Button { Text = "Update Symbol Holidays" };

        updateSymbolHolidaysButton.Click += OnUpdateSymbolHolidaysButtonClick;

        panel.AddChild(updateSymbolHolidaysButton);

        var showSymbolHolidaysButton = new Button { Text = "Show Symbol Holidays" };

        showSymbolHolidaysButton.Click += OnShowSymbolHolidaysButtonClick;

        panel.AddChild(showSymbolHolidaysButton);

        var updateSymbolSessionsButton = new Button { Text = "Update Symbol Sessions" };

        updateSymbolSessionsButton.Click += OnUpdateSymbolSessionsButtonClick;

        panel.AddChild(updateSymbolSessionsButton);

        var showSymbolSessionsButton = new Button { Text = "Show Symbol Sessions" };

        showSymbolSessionsButton.Click += OnShowSymbolSessionsButtonClick;

        panel.AddChild(showSymbolSessionsButton);

        var updateSymbolFuturesSettingsButton = new Button { Text = "Update Symbol Futures Settings" };

        updateSymbolFuturesSettingsButton.Click += OnUpdateSymbolFuturesSettingsButtonClick;

        panel.AddChild(updateSymbolFuturesSettingsButton);

        var showSymbolFuturesSettingsButton = new Button { Text = "Show Symbol Futures Settings" };

        showSymbolFuturesSettingsButton.Click += OnShowSymbolFuturesSettingsButtonClick;

        panel.AddChild(showSymbolFuturesSettingsButton);

        var block = Asp.SymbolTab.AddBlock("Custom symbol Test");
        block.Child = panel;
        block.Height = 550;

        ChartManager.FramesAdded += OnChartManagerFramesAdded;

        Symbols.Added += OnSymbolAdded;
        Symbols.Removed += OnSymbolRemoved;
    }

    private void OnShowSymbolFuturesSettingsButtonClick(ButtonClickEventArgs obj)
    {
        Print($"Last Trade Time: {_customSymbol.Symbol.FuturesSettings.LastTradeTime} | Expiration Time: {_customSymbol.Symbol.FuturesSettings.ExpirationTime} | Maintenance Margin: {_customSymbol.Symbol.FuturesSettings.MaintenanceMargin}");
    }

    private void OnUpdateSymbolFuturesSettingsButtonClick(ButtonClickEventArgs obj)
    {
        _customSymbol.FuturesSettings = new CustomSymbolFuturesSettings(Server.Time, Server.Time.AddMonths(Random.Shared.Next(1, 10)), Random.Shared.NextDouble() * 100 + 1000);
    }

    private void OnShowSymbolSessionsButtonClick(ButtonClickEventArgs obj)
    {
        Print($"Sessions Count: {_customSymbol.Symbol.MarketHours.Sessions.Count}");

        foreach (var session in _customSymbol.Symbol.MarketHours.Sessions)
        {
            Print($"Start Day: {session.StartDay} | End Day: {session.EndDay} | Start Time: {session.StartTime} | End Time: {session.EndTime}");
        }
    }

    private void OnUpdateSymbolSessionsButtonClick(ButtonClickEventArgs obj)
    {
        var startDay = (DayOfWeek)Random.Shared.Next(0, 6);
        var endDay = (DayOfWeek)((int)startDay + 1);
        var startTime = TimeSpan.FromHours(Random.Shared.Next(0, 22));
        var endTime = startTime.Add(TimeSpan.FromHours(1));

        _customSymbol.MarketHours.Sessions.Add(new CustomSymbolTradingSession(startDay, endDay, startTime, endTime));
    }

    private void OnShowSymbolHolidaysButtonClick(ButtonClickEventArgs obj)
    {
        Print($"Holidays Count: {_customSymbol.Symbol.MarketHours.Holidays.Count}");

        foreach (var holiday in _customSymbol.Symbol.MarketHours.Holidays)
        {
            Print($"Name: {holiday.Name} | Start: {holiday.StartTime:o} | End: {holiday.EndTime:o} | Is Recurring: {holiday.IsRecurring}");
        }
    }

    private void OnUpdateSymbolHolidaysButtonClick(ButtonClickEventArgs obj)
    {
        var startTime = Server.Time.AddMonths(Random.Shared.Next(1, 3));
        var endTime = startTime.AddDays(1);
        var isRecurring = Random.Shared.Next(0, 1) > 0;

        _customSymbol.MarketHours.Holidays.Add(new CustomSymbolTradingHoliday("Test " + Random.Shared.Next().ToString(), startTime, endTime, isRecurring));
    }

    private void ShowSymbolDynamicLeverage()
    {
        Print($"Dynamic Leverage Count: {_customSymbol.Symbol.DynamicLeverage.Count}");

        foreach (var leverage in _customSymbol.Symbol.DynamicLeverage)
        {
            Print($"Volume: {leverage.Volume} | Leverage: {leverage.Leverage}");
        }
    }

    private void OnUpdateSymbolDynamicLeverageButtonClick(ButtonClickEventArgs obj)
    {
        _customSymbol.DynamicLeverage.Add(new CustomSymbolLeverageTier(Random.Shared.NextDouble() * 100 + 1000, 100 + Random.Shared.Next(0, 100)));
    }

    private void OnUpdateSymbolSentimentButtonClick(ButtonClickEventArgs obj)
    {
        _customSymbol.Sentiment.BuyPercentage = _customSymbol.Sentiment.BuyPercentage < 99 ? _customSymbol.Sentiment.BuyPercentage + 1 : _customSymbol.Sentiment.BuyPercentage - 1;
    }

    private void ShowSymbolSentiment()
    {
        Print($"Buy: {_customSymbol.Symbol.Sentiment.BuyPercentage} | Sell: {_customSymbol.Symbol.Sentiment.SellPercentage}");
    }

    private void OnSymbolAdded(SymbolAddedEventArgs args)
    {
        Print($"Symbol Added: {args.SymbolName}");
    }

    private void OnSymbolRemoved(SymbolRemovedEventArgs args)
    {
        Print($"Symbol Removed: {args.SymbolName}");
    }

    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($"Changing 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 OnRemoveCustomSymbolButtonClick(ButtonClickEventArgs obj)
    {
        if (!CustomSymbols.Remove(_customSymbol))
            return;

        Print($"custom symbol '{_customSymbol.Name}' has been removed.");

        _customSymbol = null;
    }

    private void OnUpdateSymbolBaseAssetButtonClick(ButtonClickEventArgs obj)
    {
        _customSymbol.BaseAsset = Assets.GetAsset(Assets.First(a => a != _customSymbol.BaseAsset.Name && a != _customSymbol.QuoteAsset.Name));

        ShowSymbolAssets();
    }

    private void OnUpdateSymbolQuoteAssetButtonClick(ButtonClickEventArgs obj)
    {
        _customSymbol.QuoteAsset = Assets.GetAsset(Assets.First(a => a != _customSymbol.BaseAsset.Name && a != _customSymbol.QuoteAsset.Name));

        ShowSymbolAssets();
    }

    private void ShowSymbolAssets()
    {
        Print($"Base Asset: {_customSymbol.Symbol.BaseAsset.Name} | Quote Asset: {_customSymbol.Symbol.QuoteAsset.Name}");
    }

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

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

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

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

    private void OnUpdateSymbolPropertiesButtonClick(ButtonClickEventArgs obj)
    {
        _customSymbol.PipDigits = _customSymbol.PipDigits + 1;
        _customSymbol.TickDigits = _customSymbol.TickDigits + 1;
        _customSymbol.VolumeInUnitsMin = _customSymbol.VolumeInUnitsMin - 10;
        _customSymbol.VolumeInUnitsStep = _customSymbol.VolumeInUnitsStep + 10;
        _customSymbol.VolumeInUnitsMax = _customSymbol.VolumeInUnitsMax + 10;
        _customSymbol.Commission = _customSymbol.Commission + 1;
        _customSymbol.GracePeriod = _customSymbol.GracePeriod + 1;
        _customSymbol.LotSize = _customSymbol.LotSize * 2;
        _customSymbol.PnLConversionFeeRate = _customSymbol.PnLConversionFeeRate + 1;
        _customSymbol.CommissionType = SymbolCommissionType.PercentageOfTradingVolume;
        _customSymbol.MinCommission = _customSymbol.MinCommission + 1;
        _customSymbol.MinCommissionType = SymbolMinCommissionType.QuoteAsset;
        _customSymbol.AdministrativeCharge3DaysRollover = DayOfWeek.Thursday;
        _customSymbol.AdministrativeCharge = _customSymbol.AdministrativeCharge + 1;
        _customSymbol.SwapPeriod = _customSymbol.SwapPeriod + 1;
        _customSymbol.WeekendSwaps = !_customSymbol.WeekendSwaps;
        _customSymbol.SwapLong = _customSymbol.SwapLong + 1;
        _customSymbol.SwapShort = _customSymbol.SwapShort + 1;
        _customSymbol.SwapTimeInMinutes = _customSymbol.SwapTimeInMinutes + 1;
        _customSymbol.Swap3DaysRollover = DayOfWeek.Tuesday;
        _customSymbol.SwapCalculationType = SymbolSwapCalculationType.Percentage;
        _customSymbol.MinDistanceType = SymbolMinDistanceType.Pips;
        _customSymbol.MinTakeProfitDistance = _customSymbol.MinTakeProfitDistance + 1;
        _customSymbol.MinStopLossDistance = _customSymbol.MinStopLossDistance + 1;

        ShowSymbolProperties();
    }

    private void ShowSymbolProperties()
    {
        foreach (var property in _customSymbol.Symbol.GetType().GetProperties())
        {
            Print($"{property.Name}: {property.GetValue(_customSymbol.Symbol)}");
        }
    }

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

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

        var bars = _customSymbol.AddBars(chart.TimeFrame);

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

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

        var result = _customSymbol.RemoveBars(chart.TimeFrame);

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

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

    private void OnAddCustomSymbolWithBaseButtonClick(ButtonClickEventArgs obj)
    {
        var baseSymbol = Symbols.GetSymbol("EURUSD");

        _customSymbol = CustomSymbols.Add("Custom Symbol With Base", baseSymbol);

        _customSymbol.Symbol.Sentiment.Updated += OnSymbolSentimentUpdated;

        _customSymbol.Description = InitialDescription;

        _customSymbol.BarsNeeded = OnCustomSymbolBarsNeeded;

        baseSymbol.Tick += OnBaseSymbolTick;

        _customSymbol.UpdateQuote(baseSymbol.Bid, baseSymbol.Ask);

        Print($"custom symbol '{_customSymbol.Name}' has been added.");
    }

    private void OnAddCustomSymbolWithoutBaseButtonClick(ButtonClickEventArgs obj)
    {
        var baseAsset = Account.Asset;
        var quoteAsset = Assets.GetAsset(Assets.FirstOrDefault(assetName => assetName != baseAsset.Name));

        _customSymbol = CustomSymbols.Add("Custom Symbol Without Base", baseAsset, quoteAsset);

        _customSymbol.Symbol.Sentiment.Updated += OnSymbolSentimentUpdated;

        _customSymbol.Description = InitialDescription;

        _customSymbol.BarsNeeded = OnCustomSymbolBarsNeeded;

        var trackingSymbol = Symbols.GetSymbol("EURUSD");

        trackingSymbol.Tick += OnBaseSymbolTick;

        _customSymbol.UpdateQuote(trackingSymbol.Bid, trackingSymbol.Ask);

        Print($"custom symbol '{_customSymbol.Name}' has been added.");
    }

    private void OnSymbolSentimentUpdated(SymbolSentimentUpdatedEventArgs args)
    {
        Print($"SentimentUpdated, Buy: {args.Sentiment.BuyPercentage} | Sell: {args.Sentiment.SellPercentage}");
    }

    private void OnBaseSymbolTick(SymbolTickEventArgs args)
    {
        if (_customSymbol is null)
        {
            args.Symbol.Tick -= OnBaseSymbolTick;
            return;
        }

        _customSymbol.UpdateQuote(args.Symbol.Bid, args.Symbol.Ask);
    }

    private void OnCustomSymbolBarsNeeded(CustomSymbolBarsNeededArgs args)
    {
        Print($"Bars Needed for custom symbol, Symbol: {args.CustomBars.Symbol}, Name: {args.CustomSymbol.Name}");

        _customBars = args.CustomBars;

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

            Sleep(TimeSpan.FromSeconds(2));

            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(2));
                    args.CustomBars.PrependBars(bars.Take(loadedMoreArgs.Count).Select(bar => new CustomBar(bar.OpenTime, bar.Open, bar.High, bar.Low, bar.Close, (int)bar.TickVolume)));
                });
            };

            bars.BarOpened += _ =>
            {
                if (_customSymbol is null)
                    return;

                args.CustomBars.AppendBar(new CustomBar(bars.LastBar.OpenTime, bars.LastBar.Open, bars.LastBar.High, bars.LastBar.Low, bars.LastBar.Close, bars.LastBar.TickVolume));
            };

            bars.Tick += _ =>
            {
                if (_customSymbol is null)
                    return;

                args.CustomBars.UpdateLastBar(bars.LastBar.Open, bars.LastBar.High, bars.LastBar.Low, bars.LastBar.Close, bars.LastBar.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 symbol initial description"
    ChangedDescription = "This is custom symbol changed description"

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

        panel = StackPanel()

        addCustomSymbolWithBaseButton = Button()
        addCustomSymbolWithBaseButton.Text = "Add custom symbol with Base Symbol"
        addCustomSymbolWithBaseButton.Click += self.on_add_custom_symbol_with_base_button_click

        panel.AddChild(addCustomSymbolWithBaseButton)

        addCustomSymbolWithoutBaseButton = Button()
        addCustomSymbolWithoutBaseButton.Text = "Add custom symbol without Base Symbol"
        addCustomSymbolWithoutBaseButton.Click += self.on_add_custom_symbol_without_base_button_click

        panel.AddChild(addCustomSymbolWithoutBaseButton)

        removeCustomSymbolButton = Button()
        removeCustomSymbolButton.Text = "Remove custom symbol"
        removeCustomSymbolButton.Click += self.on_remove_custom_symbol_button_click

        panel.AddChild(removeCustomSymbolButton)

        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)

        updateSymbolPropertiesButton = Button()
        updateSymbolPropertiesButton.Text = "Update Symbol Properties"
        updateSymbolPropertiesButton.Click += self.on_update_symbol_properties_button_click

        panel.AddChild(updateSymbolPropertiesButton)

        updateSymbolBaseAssetButton = Button()
        updateSymbolBaseAssetButton.Text = "Update Symbol Base Asset"
        updateSymbolBaseAssetButton.Click += self.on_update_symbol_base_asset_button_click

        panel.AddChild(updateSymbolBaseAssetButton)

        updateSymbolQuoteAssetButton = Button()
        updateSymbolQuoteAssetButton.Text = "Update Symbol Quote Asset"
        updateSymbolQuoteAssetButton.Click += self.on_update_symbol_quote_asset_button_click

        panel.AddChild(updateSymbolQuoteAssetButton)

        showSymbolPropertiesButton = Button()
        showSymbolPropertiesButton.Text = "Show Symbol Properties"
        showSymbolPropertiesButton.Click += lambda _: self.show_symbol_properties()

        panel.AddChild(showSymbolPropertiesButton)

        showSymbolAssetsButton = Button()
        showSymbolAssetsButton.Text = "Show Symbol Assets"
        showSymbolAssetsButton.Click += lambda _: self.show_symbol_assets()

        panel.AddChild(showSymbolAssetsButton)

        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)

        updateSymbolSentimentButton = Button()
        updateSymbolSentimentButton.Text = "Update Symbol Sentiment"
        updateSymbolSentimentButton.Click += self.on_update_symbol_sentiment_button_click

        panel.AddChild(updateSymbolSentimentButton)

        showSymbolSentimentButton = Button()
        showSymbolSentimentButton.Text = "Show Symbol Sentiment"
        showSymbolSentimentButton.Click += lambda _: self.show_symbol_sentiment()

        panel.AddChild(showSymbolSentimentButton)

        updateSymbolDynamicLeverageButton = Button()
        updateSymbolDynamicLeverageButton.Text = "Update Symbol Dynamic Leverage"
        updateSymbolDynamicLeverageButton.Click += self.on_update_symbol_dynamic_leverage_button_click

        panel.AddChild(updateSymbolDynamicLeverageButton)

        showSymbolDynamicLeverageButton = Button()
        showSymbolDynamicLeverageButton.Text = "Show Symbol Dynamic Leverage"
        showSymbolDynamicLeverageButton.Click += lambda _: self.show_symbol_dynamic_leverage()

        panel.AddChild(showSymbolDynamicLeverageButton)

        updateSymbolHolidaysButton = Button()
        updateSymbolHolidaysButton.Text = "Update Symbol Holidays"
        updateSymbolHolidaysButton.Click += self.on_update_symbol_holidays_button_click

        panel.AddChild(updateSymbolHolidaysButton)

        showSymbolHolidaysButton = Button()
        showSymbolHolidaysButton.Text = "Show Symbol Holidays"
        showSymbolHolidaysButton.Click += self.on_show_symbol_holidays_button_click

        panel.AddChild(showSymbolHolidaysButton)

        updateSymbolSessionsButton = Button()
        updateSymbolSessionsButton.Text = "Update Symbol Sessions"
        updateSymbolSessionsButton.Click += self.on_update_symbol_sessions_button_click

        panel.AddChild(updateSymbolSessionsButton)

        showSymbolSessionsButton = Button()
        showSymbolSessionsButton.Text = "Show Symbol Sessions"
        showSymbolSessionsButton.Click += self.on_show_symbol_sessions_button_click

        panel.AddChild(showSymbolSessionsButton)

        updateSymbolFuturesSettingsButton = Button()
        updateSymbolFuturesSettingsButton.Text = "Update Symbol Futures Settings"
        updateSymbolFuturesSettingsButton.Click += self.on_update_symbol_futures_settings_button_click

        panel.AddChild(updateSymbolFuturesSettingsButton)

        showSymbolFuturesSettingsButton = Button()
        showSymbolFuturesSettingsButton.Text = "Show Symbol Futures Settings"
        showSymbolFuturesSettingsButton.Click += self.on_show_symbol_futures_settings_button_click

        panel.AddChild(showSymbolFuturesSettingsButton)

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

        api.ChartManager.FramesAdded += self.on_chart_manager_frames_addded

        api.Symbols.Added += self.on_symbol_added
        api.Symbols.Removed += self.on_symbol_removed

    def on_add_custom_symbol_with_base_button_click(self, args):
        baseSymbol = api.Symbols.GetSymbol("EURUSD")

        self.customSymbol = api.CustomSymbols.Add("Custom Symbol With Base", baseSymbol)
        self.customSymbol.Symbol.Sentiment.Updated += self.on_symbol_sentiment_updated
        self.customSymbol.Description = self.InitialDescription
        self.customSymbol.BarsNeeded = Action[CustomSymbolBarsNeededArgs](self.on_custom_symbol_bars_needed)

        baseSymbol.Tick += self.on_base_symbol_tick

        self.customSymbol.UpdateQuote(baseSymbol.Bid, baseSymbol.Ask)

        print(f"custom symbol '{self.customSymbol.Name}' has been added.")

    def on_add_custom_symbol_without_base_button_click(self, args):
        baseAsset = api.Account.Asset
        quoteAsset = api.Assets.GetAsset(next((assetName for assetName in api.Assets if assetName != baseAsset.Name)))

        self.customSymbol = api.CustomSymbols.Add("Custom Symbol Without Base", baseAsset, quoteAsset)
        self.customSymbol.Symbol.Sentiment.Updated += self.on_symbol_sentiment_updated
        self.customSymbol.Description = self.InitialDescription
        self.customSymbol.BarsNeeded = Action[CustomSymbolBarsNeededArgs](self.on_custom_symbol_bars_needed)

        trackingSymbol = api.Symbols.GetSymbol("EURUSD")
        trackingSymbol.Tick += self.on_base_symbol_tick

        self.customSymbol.UpdateQuote(trackingSymbol.Bid, trackingSymbol.Ask)

        print(f"custom symbol '{self.customSymbol.Name}' has been added.")

    def on_symbol_sentiment_updated(self, args):
        print(f"SentimentUpdated, Buy: {args.Sentiment.BuyPercentage} | Sell: {args.Sentiment.SellPercentage}")

    def on_custom_symbol_bars_needed(self, args):
        print(f"Bars Needed for custom symbol, Symbol: {args.CustomBars.Symbol}, Name: {args.CustomSymbol.Name}")

        self.customBars = args.CustomBars

        api.MarketData.GetBarsAsync(args.CustomBars.TimeFrame, "EURUSD", 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.customSymbol 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.customSymbol is None:
            return

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

    def on_base_symbol_tick(self, args):
        if self.customSymbol is None:
            args.Symbol.Tick -= self.on_base_symbol_tick
            return

        self.customSymbol.UpdateQuote(args.Symbol.Bid, args.Symbol.Ask)

    def on_remove_custom_symbol_button_click(self, args):
        if api.CustomSymbols.Remove(self.customSymbol):
            return

        print(f"custom symbol '{self.customSymbol.Name}' has been removed.")
        self.customSymbol = 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.customSymbol.Description = self.ChangedDescription if self.customSymbol.Description == self.InitialDescription else self.InitialDescription
        print(f"Changed description to: {self.customSymbol.Description}")

    def on_update_symbol_properties_button_click(self, args):
        self.customSymbol.PipDigits = self.customSymbol.PipDigits + 1
        self.customSymbol.TickDigits = self.customSymbol.TickDigits + 1
        self.customSymbol.VolumeInUnitsMin = self.customSymbol.VolumeInUnitsMin - 10
        self.customSymbol.VolumeInUnitsStep = self.customSymbol.VolumeInUnitsStep + 10
        self.customSymbol.VolumeInUnitsMax = self.customSymbol.VolumeInUnitsMax + 10
        self.customSymbol.Commission = self.customSymbol.Commission + 1
        self.customSymbol.GracePeriod = self.customSymbol.GracePeriod + 1
        self.customSymbol.LotSize = self.customSymbol.LotSize * 2
        self.customSymbol.PnLConversionFeeRate = self.customSymbol.PnLConversionFeeRate + 1
        self.customSymbol.CommissionType = SymbolCommissionType.PercentageOfTradingVolume
        self.customSymbol.MinCommission = self.customSymbol.MinCommission + 1
        self.customSymbol.MinCommissionType = SymbolMinCommissionType.QuoteAsset
        self.customSymbol.AdministrativeCharge3DaysRollover = DayOfWeek.Thursday
        self.customSymbol.AdministrativeCharge = self.customSymbol.AdministrativeCharge + 1
        self.customSymbol.SwapPeriod = self.customSymbol.SwapPeriod + 1
        self.customSymbol.WeekendSwaps = not self.customSymbol.WeekendSwaps
        self.customSymbol.SwapLong = self.customSymbol.SwapLong + 1
        self.customSymbol.SwapShort = self.customSymbol.SwapShort + 1
        self.customSymbol.SwapTimeInMinutes = self.customSymbol.SwapTimeInMinutes + 1
        self.customSymbol.Swap3DaysRollover = DayOfWeek.Tuesday
        self.customSymbol.SwapCalculationType = SymbolSwapCalculationType.Percentage
        self.customSymbol.MinDistanceType = SymbolMinDistanceType.Pips
        self.customSymbol.MinTakeProfitDistance = self.customSymbol.MinTakeProfitDistance + 1
        self.customSymbol.MinStopLossDistance = self.customSymbol.MinStopLossDistance + 1

        self.show_symbol_properties()

    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 show_symbol_properties(self):
        for propertyInfo in self.customSymbol.Symbol.GetType().GetProperties():
            print(f"{propertyInfo.Name}: {propertyInfo.GetValue(self.customSymbol.Symbol)}")

    def on_update_symbol_base_asset_button_click(self, args):
        self.customSymbol.BaseAsset = api.Assets.GetAsset(next((assetName for assetName in api.Assets if assetName != self.customSymbol.BaseAsset.Name and assetName != self.customSymbol.QuoteAsset.Name)))
        self.show_symbol_assets()

    def on_update_symbol_quote_asset_button_click(self, args):
        self.customSymbol.QuoteAsset = api.Assets.GetAsset(next((assetName for assetName in api.Assets if assetName != self.customSymbol.BaseAsset.Name and assetName != self.customSymbol.QuoteAsset.Name)))
        self.show_symbol_assets()

    def show_symbol_assets(self):
        print(f"Base Asset: {self.customSymbol.Symbol.BaseAsset.Name} | Quote Asset: {self.customSymbol.Symbol.QuoteAsset.Name}")

    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.customSymbol.AddBars(chart.TimeFrame)
        print(f"Added Bars, Count: {bars.Bars.Count}, Get: {bars == self.customSymbol.GetBars(chart.TimeFrame)}")

    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.customSymbol.RemoveBars(chart.TimeFrame)
        print(f"Removed Bars, Result: {result}, Get is None: {self.customSymbol.GetBars(chart.TimeFrame) 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_update_symbol_sentiment_button_click(self, args):
        self.customSymbol.Sentiment.BuyPercentage = self.customSymbol.Sentiment.BuyPercentage + 1 if self.customSymbol.Sentiment.BuyPercentage < 99 else self.customSymbol.Sentiment.BuyPercentage - 1

    def show_symbol_sentiment(self):
        print(f"Buy: {self.customSymbol.Symbol.Sentiment.BuyPercentage} | Sell: {self.customSymbol.Symbol.Sentiment.SellPercentage}")

    def on_update_symbol_dynamic_leverage_button_click(self, args):
        self.customSymbol.DynamicLeverage.Add(CustomSymbolLeverageTier(random.random() * 100 + 1000, 100 + random.randint(0, 100)))

    def show_symbol_dynamic_leverage(self):
        print(f"Dynamic Leverage Count: {self.customSymbol.Symbol.DynamicLeverage.Count}")
        for leverage in self.customSymbol.Symbol.DynamicLeverage:
            print(f"Volume: {leverage.Volume} | Leverage: {leverage.Leverage}")

    def on_update_symbol_holidays_button_click(self, args):
        startTime = api.Server.Time.AddMonths(random.randint(1, 3))
        endTime = startTime.AddDays(1)
        isRecurring = random.randint(0, 1) > 0
        self.customSymbol.MarketHours.Holidays.Add(CustomSymbolTradingHoliday(f"Test {self.customSymbol.MarketHours.Holidays.Count}", startTime, endTime, isRecurring))

    def on_show_symbol_holidays_button_click(self, args):
        print(f"Holidays Count: {self.customSymbol.Symbol.MarketHours.Holidays.Count}")

        for holiday in self.customSymbol.Symbol.MarketHours.Holidays:
            print(f"Name: {holiday.Name} | Start: {holiday.StartTime} | End: {holiday.EndTime} | Is Recurring: {holiday.IsRecurring}")

    def on_update_symbol_sessions_button_click(self, args):
        startDay = DayOfWeek(random.randint(0, 6))
        endDay = DayOfWeek(int(startDay) + 1)
        startTime = TimeSpan.FromHours(random.randint(0, 22))
        endTime = startTime.Add(TimeSpan.FromHours(1))
        self.customSymbol.MarketHours.Sessions.Add(CustomSymbolTradingSession(startDay, endDay, startTime, endTime))

    def on_show_symbol_sessions_button_click(self, args):
        print(f"Sessions Count: {self.customSymbol.Symbol.MarketHours.Sessions.Count}")

        for session in self.customSymbol.Symbol.MarketHours.Sessions:
            print(f"Start Day: {session.StartDay} | End Day: {session.EndDay} | Start Time: {session.StartTime} | End Time: {session.EndTime}")

    def on_update_symbol_futures_settings_button_click(self, args):
        self.customSymbol.FuturesSettings = CustomSymbolFuturesSettings(api.Server.Time, api.Server.Time.AddMonths(random.randint(1, 10)), random.random() * 100 + 1000)

    def on_show_symbol_futures_settings_button_click(self, args):
        symbol = self.customSymbol.Symbol
        print(f"Last Trade Time: {symbol.FuturesSettings.LastTradeTime} | Expiration Time: {symbol.FuturesSettings.ExpirationTime} | Maintenance Margin: {symbol.FuturesSettings.MaintenanceMargin}")

    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_symbol_added(self, args):
        print(f"Symbol Added: {args.SymbolName}")

    def on_symbol_removed(self, args):
        print(f"Symbol Removed: {args.SymbolName}")
{
  "AccessRights": "None"
}

Methods

Name Description
Add 2 overloadsDesktopCLICloudCustomSymbol Adds a new custom symbol.
GetDesktopCLICloudCustomSymbol Returns a custom symbol by it's name.
RemoveDesktopCLICloudbool Removes a custom symbol.

See also