background

Центр поддержки Tradematic

Материалы, видео и ссылки для пользователей и разработчиков Tradematic.

Размер позиции в зависимости от волатильности рынка

80436СТАТЬЯ РЕДАКТОР КОДА ПРИМЕР ДИНАМИЧЕСКИЙ РАЗМЕР ПОЗИЦИИ РАЗМЕР ПОЗИЦИИ В ЗАВИСИМОСТИ ОТ ВОЛАТИЛЬНОСТИ РЫНКА

В этом примере мы рассмотрим создание функции, которая будет определять размер каждой позиции в зависимости от волатильности рынка на момент входа в позицию.
Этот пример похож на первый пример, т.к. перегружает ту же функцию CalculatePositionSize().

Чтобы контролировать из кода стратегии размер позиции, нужно перегрузить функцию CalculatePositionSize в классе TradeMatic.Script.
Эта функция возвращает размер позиции (объект PositionSize), а на вход принимает следующие параметры:

  • Position p - описание позиции, нам оно понадобится, чтобы выяснить название инструмента
  • double cash - размер свободных денежных средств на момент открытия позиции
  • double equity - размер активов на момент открытия позиции

А чтобы вызывалась эта функция, нужно в свойствах стратегии в параметре "Размер позиции" выбрать "Функция".

Для измерения волатильности рынка мы будем использовать индикатор ATR с параметром 60 (можно указать любой другой, разумеется).

Таким образом, итоговая формула для расчета доли от стоимости капитала, на которую мы будем входить в каждую позицию:
РАЗМЕР_ПОЗИЦИИ = 0.0065 * Close / ATR(60)

Для расчета формулы нам нужно получить значение цены закрытия (Close) в момент входа в позицию (p.EntryBar):

// получим цену закрытия на момент входа в позицию
double close = p.Symbol.Close[p.EntryBar];

Кроме того, нам нужно получить значение индикатора ATR в определенном баре - баре входа в позицию:

// получим значение индикатора ATR на момент входа в позицию
double atr = ATR.Value(p.EntryBar, p.Symbol.High, p.Symbol.Low, p.Symbol.Close, 60);

Вот получившаяся функция:

public override PositionSize CalculatePositionSize(Position p, double cash, double equity)
{
   // получим цену закрытия на момент входа в позицию
   double close = p.Symbol.Close[p.EntryBar];
         
   // получим значение индикатора ATR на момент входа в позицию
   double atr = ATR.Value(p.EntryBar, p.Symbol.High, p.Symbol.Low, p.Symbol.Close, 60);
         
   return new PositionSize(PositionSizeMode.PercentOfEquity, 0.0065 * close / atr);
}

В качестве основы мы в который раз взяли код стратегии "SMA-9" (для наглядности).

Итоговый код стратегии должен получиться такой:

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using TradeMatic;
using TradeMatic.Indicators;

namespace ScriptNamespace
{
   class MyScript : Script
   {
      private StrategyParameter parameter0;
      private StrategyParameter parameter1;

      public MyScript()
      {
         parameter0 = CreateParameter("Период SMA", 9, 0, 100, 1);
         parameter1 = CreateParameter("Период SMA", 9, 0, 100, 1);
      }

      public override PositionSize CalculatePositionSize(Position p, double cash, double equity)
      {
         // получим цену закрытия на момент входа в позицию
         double close = p.Symbol.Close[p.EntryBar];
         
         // получим значение индикатора ATR на момент входа в позицию
         double atr = ATR.Value(p.EntryBar, p.Symbol.High, p.Symbol.Low, p.Symbol.Close, 60);
         
         return new PositionSize(PositionSizeMode.PercentOfEquity, 0.0065 * close / atr);
      }
      
      public override void Execute()
      {
         // Отрисовка
         PlotSeries(PricePane, SMA.Series(Close, parameter0.ValueInt), Color.Red, LineStyle.Solid, 1);
         PlotSeries(PricePane, SMA.Series(Close, parameter1.ValueInt), Color.Red, LineStyle.Solid, 1);

         // Инициализация

         // Основной цикл
         for (int bar = 9; bar < Symbol.Count; bar++)
         {
            if (IsLastPositionActive)
            {
               if (CrossUnder(bar, Close, SMA.Series(Close, parameter1.ValueInt)))
               {
                  SellAtClose(bar, LastPosition, "");
               }
            }
            else
            {
               if (CrossOver(bar, Close, SMA.Series(Close, parameter0.ValueInt)))
               {
                  BuyAtClose(bar, "");
               }
            }
         }
      }
   }
}