TSLab
TSLab.proSupportTSLab LiveTSVerse
Eng
Eng
  • TSLab trading platform
  • For newbies
    • A beginner's guide
      • Purchasing a license key for a data provider
      • An example of connecting text quotes
      • Example of connecting a data provider to a broker / exchange
      • An example of creating a script in TSLab
      • An example of creating a trading algorithm in TSLab
  • Installing TSLab
    • TSLab Installation Guide
      • System requirements
      • TSLab Installation manual
    • Update TSLab
      • Preparing for update
      • Release build
      • Nightly build
    • Restarting the TSLab program
    • TSLab Changelog
      • TSLab 2.1 Changelog
      • TSLab 2.2 Changelog
        • 2.2.26.0 - 2024/01/31
        • 2.2.25.0 - 2024/01/17
        • 2.2.24.0 - 2024/12/04
        • 2.2.23.0 - 2024/09/19
        • 2.2.22.0 - 2024/08/30
        • 2.2.21.0 - 2024/05/17
        • 2.2.20.0 - 2024/05/15
        • 2.2.19.0 - 2024/02/21
        • 2.2.18.0 - 2024/02/09
        • 2.2.17.0 - 2023/11/16
        • 2.2.16.0 - 2023/10/20
        • 2.2.15.0 - 2023/10/13
        • 2.2.14.0 - 2023/08/11
        • 2.2.13.0 - 2023/05/12
        • 2.2.12.0 - 2023/02/28
        • 2.2.11.0 - 2022/12/15
        • 2.2.10.0 - 2022/10/27
        • 2.2.9.0 - 2022/09/16
        • 2.2.7.0 - 2022/06/23
        • 2.2.5.0 - 2022/04/29
        • 2.2.3.0 - 2022/04/01
        • 2.2.2.0 - 2021/12/29
  • Data providers
    • Cryptocurrency exchanges
      • Binance Cryptocurrency Exchange
        • Registration on Binance
          • Registration on Binance Exchange website
          • Configure Binance Wallet
          • Creating a Binance API Key for TSLab
          • Binance. Transferring USDT from wallet to wallet without commission
        • Registration on TSLab [Binance]
          • Account registration on the TSLab website [Binance]
          • Creating a free Binance Data Provider for TSLab
        • Setting up a Binance Data Provider in TSLab
        • TSLab Binance Edition
          • Starting the program
          • Configuring the Binance Data provider
      • Bitget Cryptocurrency Exchange
        • Registration on the Bitget official website
        • Creating a Free Bitget Data Provider
        • Configuring the Bitget Data Provider in TSLab
      • ByBit Cryptocurrency Exchange
        • Registration on the ByBit website
        • Creating a free ByBit data provider
        • Configuring the ByBit Data Provider in TSLab
      • Deribit Cryptocurrency Exchange
        • Deribit data provider settings
        • Deribit. Frequently asked questions and useful information
        • Deribit. Possible problems and solutions
        • Deribit Margin Requirements Calculation
        • An example of a ready-made script for Deribit
      • Kucoin Cryptocurrency Exchange
        • Registration on the KuCoin official website
        • Creating an API key on the KuCoin website
        • Issuing a free license for KuCoin Data Provider
        • Setting up the KuCoin data provider in TSLab
      • OKX Cryptocurrency Exchange
        • Setting up an OKX account
          • Registration on the OKX website
          • OKX API Key creation
          • Issuing a free license for OKX Data Provider
          • Setting up the OKX data provider in TSLab
          • OKX demo account
        • TSLab OKX Edition
          • First launch of TSLab OKEx Edition
          • Configuring the OKEx data provider
          • Trading in TSLab [OKEx]
          • OKEx Demo
    • Historical Data
      • YahooFinance
      • Offline data provider in CSV format
      • An example of connecting text quotes
      • Text files with historical data
    • Interactive Brokers
      • Getting Started with Interactive Brokers Data Provider
        • Installing and configuring the Trader Workstation (TWS) terminal
        • Installing and configuring the IB Gateway terminal
      • Features of working with Interactive Brokers data provider
      • Known issues for Interactive Brokers Data Provider
      • Loading instruments in a package
  • Working with the program
    • Main menu
      • File
        • Program Settings
      • View
        • Chart
          • Features of working with the Chart in TSLab
          • Chart Controls
        • Depth of Market
        • Quotes
        • All Trades
      • Data
        • Data Providers window
        • Add online data provider
        • Add offline data provider
      • Lab
        • Scripts window
          • Script Container
      • Trading
        • Accounts window
        • Positions window
        • My trades window
        • My orders window
          • Move orders and deals to an agent
        • Autotrading Control Center window
          • Agent window
          • Agent trading settings
            • Event recalculations
            • Slippage
          • "Forget errors" of the agent
        • Orders manager
          • Linking a manually completed order to an agent
        • Agent Control Center window
      • Tools
        • Data backup and recovery
        • Notifications manager
          • Notifications Manager Filters
          • Reference List of Service Message Numbers
          • Example of setting up notifications for Gmail
        • Export to Excel
    • Common interface
      • Status bar
      • Tab
      • Workspace
      • Spreadsheets
    • Visual editor
      • Toolbar
        • Compress and Decompress Blocks
      • List of visual blocks
        • Service Elements
        • Cycles
        • TSChannel
      • The syntax of the Formula, Boolean expression and String expression blocks.
    • Autotrading Control Center
      • Agent trade settings
        • Agent trade settings - Placing orders
        • Agent trading settings - Script execution
        • Agent trading settings - Events
    • TSLab API
      • API Introduction
        • Visual Studio Installation
        • First script (API)
        • First Indicator (API)
        • Script Debugging
        • Logging
      • Writing scripts on the API
        • Trading Instrument Data
        • Working with positions
        • List of deals
        • The order queue
        • Standard Indicators and Handlers
        • Script parameters
        • Caching
        • Local and global cache
        • Multiple Tools
      • Writing indicators on the API
        • Stream indicator
        • Bar indicator
        • Pre-processed indicator
        • Indicator with multiple calculations
      • Additional features
        • The ability to create your own optimizers *
        • C ++ / CLI script
        • API Control Panel
        • Result from script
        • * Оптимизация. Пул массивов.
      • Examples
        • Get script results
        • Get script parameters
        • Get script and agent settings
        • Get position balance (net worth)
        • An example of a strategy Breakout of the Donchian channel
        • Example of a Moving Average Crossover strategy
        • Indicator example
        • How to speed up the processing of a script on the API
        • Links to examples
      • Question - Answer
        • HandlerParameter Attribute
    • Optimization
      • Insufficient load on a multicore processor
  • Examples of scripts and indicators
    • Examples of algorithms and indicators
    • Examples of implementing strategies in TSLab
      • A trading system based on indicator CCI
      • A trading system based on Standard Deviation
      • A trading system based on Aroon
      • A trading system based on ADX and DI technical indicators
      • A trading system based on the RSI indicator
      • Example of a trading strategy without parameters
  • TSLab website
    • TSLab Support Service
      • Memory dump of TSLab application
      • TSLab program log files
Powered by GitBook
LogoLogo

Мы в соцсетях

  • Группа в Telegram
  • Новости TSLab
  • Vkontakte
  • YouTube канал TSLab Live

Наши веб-сайты

  • TSLab
  • Служба поддержки
On this page

Was this helpful?

Export as PDF
  1. Working with the program
  2. TSLab API
  3. Writing indicators on the API

Indicator with multiple calculations

Last updated 1 year ago

Was this helpful?

Blocks have a limitation in TSLab, a block can only produce one value. There are situations when one indicator must calculate several values and all of them must be used in the script.

For example, we want to write a Bollinger indicator, and in the script we want to use the upper line, lower line and channel width. To calculate these values, it is enough to calculate the average SMA line and the standard deviation StDev.

Let's write a universal MyBollinger block, which, depending on the parameters, can issue the top line, bottom line, or the width of the Bollinger. The block will have the following parameters:

  • Period is the indicator calculation period.

  • Coef is the indicator calculation coefficient

  • Type is an enumeration type that specifies how the indicator is calculated. If Top, then displays the top line. If Bottom, then displays the bottom line. If Width, then displays the width of the channel.

The formulas are: Upper line: SMA + StDev * Coef. Bottom line: SMA - StDev * Coef. Channel width: top line - bottom line.

We will calculate the SMA and StDev indicators through caching (Context.GetData). This will reduce the number of identical calculations. For example, let's add one block for the top line, one block for the bottom line, and one block for the channel width to the script. When the script is executed, the first block will calculate the SMA, StDev values and write them to the cache. Then the second and third blocks will no longer calculate these values, they will simply take them from the cache.

Important: you need to cache indicators with a full chain of dependent parameters (more details ). For this, the INeedVariableParentNames interface has been added, it has one VariableParentNames property, which contains the names of parent blocks with parameters. We will add this property to all caches of calculated indicators in order to accurately identify the incoming IList<double> values.

using System.Collections.Generic;
using System.ComponentModel;
using TSLab.Script.Handlers;
using TSLab.Script.Helpers;

namespace MyLib
{
    [HandlerCategory("MyLib")]
    [HandlerName("MyBollinger")]
    [Description("Рассчитывает верхнюю, нижнюю линию или ширину боллинжера")]
    [InputsCount(1)]
    [Input(0, TemplateTypes.DOUBLE)]
    [OutputsCount(1)]
    [OutputType(TemplateTypes.DOUBLE)]
    public class MyBollinger : IStreamHandler, IContextUses, INeedVariableParentNames
    {
        public enum MyBollingerType
        {
            Top,
            Bottom,
            Width
        }

        [HandlerParameter(true, "20", Min = "1", Max = "100", Step = "1")]
        public int Period { get; set; }

        [HandlerParameter(true, "2", Min = "1", Max = "4", Step = "0.1")]
        public double Coef { get; set; }

        [HandlerParameter(true, nameof(MyBollingerType.Top))]
        public MyBollingerType Type { get; set; }

        public IContext Context { get; set; }

        /// <summary>
        /// Тут будет список наименований родительских блоков с параметрами. В виде строки.
        /// Нужно для правильного кеширования индикаторов SMA и StDev.
        /// </summary>
        public string VariableParentNames { get; set; }

        public IList<double> Execute(IList<double> values)
        {
            // Получить скользящую среднюю (SMA)
            var sma = Context.GetData("SMA", new[] { VariableParentNames, Period.ToString() },
                () => GetSma(Context, values, Period));

            // Получить стандартное отклонение (StDev)
            var stdev = Context.GetData("StDev", new[] { VariableParentNames, Period.ToString() },
                () => GetStDev(Context, values, Period));

            var array = Context.GetArray<double>(values.Count);
            switch (Type)
            {
                case MyBollingerType.Top:
                    // Если считаем верхнюю линию боллинжера, то складываем: SMA + StDev * Coef.
                    for (int i = 0; i < values.Count; i++)
                        array[i] = sma[i] + stdev[i] * Coef;
                    break;

                case MyBollingerType.Bottom:
                    // Если считаем нижнюю линию боллинжера, то вычитаем: SMA - StDev * Coef.
                    for (int i = 0; i < values.Count; i++)
                        array[i] = sma[i] - stdev[i] * Coef;
                    break;

                case MyBollingerType.Width:
                    // Если считаем ширину канала, то из верхней линии боллинжера вычитаем нижнюю.
                    for (int i = 0; i < values.Count; i++)
                        array[i] = (sma[i] + stdev[i] * Coef) - (sma[i] - stdev[i] * Coef);
                    break;
            }
            return array;
        }

        public static IList<double> GetSma(IContext ctx, IList<double> values, int period)
        {
            // Выводим в лог сколько раз вызвался этот метод при расчете скрипта.
            // Для одного боллинжера с одинаковыми параметрами будет только одни запуск этого метода.
            // Это только для демонстрации, в 'боевых' индикаторах вывод в лог не обязателен.
            ctx.Log($"Get sma", toMessageWindow: true);
            return Series.SMA(values, period, ctx);
        }

        public static IList<double> GetStDev(IContext ctx, IList<double> values, int period)
        {
            // Выводим в лог сколько раз вызвался этот метод при расчете скрипта.
            // Для одного боллинжера с одинаковыми параметрами будет только одни запуск этого метода.
            // Это только для демонстрации, в 'боевых' индикаторах вывод в лог не обязателен.
            ctx.Log($"Get stdev", toMessageWindow: true);
            return Series.StDev(values, period, ctx);
        }
    }
}

here