background

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

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

Примеры использования нестандартного размера позиции в Tradematic Trader

118835СТАТЬЯ РЕДАКТОР КОДА РАЗМЕР ПОЗИЦИИ CALCULATEPOSITIONSIZE POSITIONSIZE POSITIONSIZEMODE ФУНКЦИЯ

С этой статьи мы начинаем цикл статей, описывающих нюансы использования Tradematic Trader — конструктора торговых роботов.
В первой статье мы рассмотрим несколько вариантов нестандартного расчета размера позиции на вход.

Первая статья будет посвящена нестандартному расчету размера позиции на вход.

Типы расчета размера позиции в Tradematic Trader.

В Трейдматике при создании стратегии вы можете выбрать один из следующих типов расчета позиции:
- Фиксированная сумма
- Фиксированное количество
- Процент от капитала
- Максимальный риск
- Функция в скрипте

Первые два параметра можно использовать, если вы хотите протестировать вашу торговую стратегию без капитализации – вход будет всегда на одну и ту же сумму либо на одно и то же фиксированное количество инструментов.

Параметр “Процент от капитала” говорит сам за себя – трейдматик входит в позицию на определенный процент от капитала. Например, при стоимости вашего портфеля в 100 000 руб., проценте 50% и стоимости инструмента в 10 руб., при поступлении сигнала на вход будет куплено 5 000 инструментов.

Параметр “Максимальный риск” мы подробно обсудим в одной из ближайших статей.

Если вас ни один из этих типов расчета размера позиции не устраивает, вы можете реализовать свой вариант – это одно из многих преимуществ Tradematic Trader перед другими программами, и одно из преимуществ современной платформы Microsoft .NET, на базе которой создан Tradematic Trader.

 

Своя функция расчета размера позиции.

Чтобы контролировать из кода стратегии размер позиции, нужно отметить в качестве типа размера позиции “Функцию в скрипте”, затем открыть встроенный редактор кода на вкладке “Алгоритм”, кнопка “Редактор исходного кода”.

Давайте более детально рассмотрим, что нам нужно будет сделать.

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

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

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

 

Пример 1. Покупка одного инструмента на 40%, а другого — на 60%

Для примера мы установим размера позиции для Газпрома 40%, для Сбербанка — 60%.

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

public override PositionSize CalculatePositionSize(Position p, double cash, double equity)
{ 
	if(p.Symbol.SymbolName == "ГАЗПРОМ ао") 
	{  
		return new PositionSize(PositionSizeMode.PercentOfEquity, 40); 
	} 
	else if(p.Symbol.SymbolName == "Сбербанк") 
	{  
		return new PositionSize(PositionSizeMode.PercentOfEquity, 60); 
	} 

	return null;
}

Не забудьте в свойствах стратегии на вкладке "Список инструментов" указать выбранные инструменты.
В качестве основы мы взяли код стратегии "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)  
		{   
			if(p.Symbol.SymbolName == "ГАЗПРОМ ао")   {    return new PositionSize(PositionSizeMode.PercentOfEquity, 40);   }   
			else if(p.Symbol.SymbolName == "Сбербанк")   {    return new PositionSize(PositionSizeMode.PercentOfEquity, 60);   }   
			return null;  
		}     

		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, "");     
					}    
				}   
			}  
		} 
	}
}

Запускаем тестирование нашей стратегии, и смотрим на вкладку “Сделки”.

Для Газпрома у нас размер позиции получился 40% от капитала, для Сбербанка – 60%.

 

Пример 2. Разный размер позиции для длинных и коротких позиций.

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

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

public override PositionSize CalculatePositionSize(Position p, double cash, double equity)
{        
	// длинная позиция? 
	if(p.PositionType == PositionType.Long) 
	{                
		// заходим 4-мя инструментами  
		return new PositionSize(PositionSizeMode.FixedShare, 4); 
	} 
	else 
	{                
		// короткая позиция - заходим 2-мя инструментами  
		return new PositionSize(PositionSizeMode.FixedShare, 2); 
	}
}

Если нужно в качестве размера позиции вместо фиксированного количества акций (контрактов) указать, к примеру, процент от активов (25%, к примеру):

return new PositionSize(PositionSizeMode.PercentOfEquity, 25);

В качестве основы мы снова берем код стратегии "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;
		private StrategyParameter parameter2;
		private StrategyParameter parameter3;

		public MyScript()
		{
			parameter0 = CreateParameter("Период SMA (LE)", 9, 0, 100, 1);
			parameter1 = CreateParameter("Период SMA (LX)", 9, 0, 100, 1);
			parameter2 = CreateParameter("Период SMA (SE)", 9, 0, 1000, 1);
			parameter3 = CreateParameter("Период SMA (SX)", 9, 0, 1000, 1);
		}

		public override PositionSize CalculatePositionSize(Position p, double cash, double equity)
		{
			// длинная позиция?
			if(p.PositionType == PositionType.Long)
			{
				// заходим 4-мя контрактами
				return new PositionSize(PositionSizeMode.FixedShare, 4);
			}
			else
			{
				// короткая позиция — заходим 2-мя контрактами
				return new PositionSize(PositionSizeMode.FixedShare, 2);
			}
		}

		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);
			PlotSeries(PricePane, SMA.Series(Close, parameter2.ValueInt), Color.Red, LineStyle.Solid, 1);
			PlotSeries(PricePane, SMA.Series(Close, parameter3.ValueInt), Color.Red, LineStyle.Solid, 1);

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

			// Основной цикл
			for (int bar = 9; bar < Symbol.Count; bar++)
			{
				if (MarketPosition == 1)
				{
					// Выход из длинной позиции
					if ((CrossUnder(bar, Close, SMA.Series(Close, parameter1.ValueInt))))
					{
						SellAtClose(bar, LastPosition, "");
					}
				}
				else if (MarketPosition == -1)
				{
					// Выход из короткой позиции
					if ((CrossOver(bar, Close, SMA.Series(Close, parameter3.ValueInt))))
					{
						CoverAtClose(bar, LastPosition, "");
					}
				}

				if (MarketPosition == 0)
				{
					// Вход в длинную позицию
					if ((CrossOver(bar, Close, SMA.Series(Close, parameter0.ValueInt))))
					{
						BuyAtClose(bar, "");
					}
				}

				if (MarketPosition == 0)
				{
					// Вход в короткую позицию
					if ((CrossUnder(bar, Close, SMA.Series(Close, parameter2.ValueInt))))
					{
						ShortAtClose(bar, "");
					}
				}
			}
		}
	}
}

Запускаем тестирование и смотрим вкладку “Сделки”: