
Tradematic Support Center
Guides, articles, videos and links for Tradematic users and developers.
Пример использования новой функции Tradematic Trader — «мультипозиции» («пирамидинг»)
145295СТАТЬЯ РЕДАКТОР КОДА МУЛЬТИПОЗИЦИИ ПИРАМИДИНГ НАРАЩИВАНИЕ ПОЗИЦИИ ENTRYSIGNAL ACTIVEPOSITIONSСтатья посвящена появлению нового функционала в Tradematic Trader — возможности наращивать или уменьшать позицию по инструменту.
Мультипозиции — что это?
Иногда требуется открывать позицию не сразу на весь объем, а постепенно — наращивая размер позиции по мере срабатывания условий. Или закрывать позицию не полностью. Начиная с версии 1.7.3, Tradematic Trader поддерживает эту возможность.
Как реализовано?
Фактически, мультипозиции — это несколько открытых позиций по одному инструменту в одном направлении. При синхронизации счета с такой стратегией считается чистая позиция по всем активным позициям, и уже с ней выполняется синхронизация. На данный момент для использования мультипозиций требуется вносить изменения в исходный код скрипта через встроенный Редактор кода.
Пример использования мультипозиций
В нашем примере мы будем использовать три группы условий, каждая группа будет входить на 10% от капитала по одному инструменту. При срабатывании всех трех условий на вход суммарная позиция будет 30% по инструменту, при срабатывании всех трех условий на выход — позиция будет 0, при срабатывании части условий — 10% или 20%.
Группировать условия можно с помощью последнего параметра в функциях BuyAt.. и SellAt.. — названия сигнала:
BuyAtClose(bar, "SMA2");У нас будет три группы:
1) Группа «SMA1»:
вход, если Close > SMA(6),
 
выход — Close < SMA(6)
2) Группа «SMA2»:
вход, если Close > SMA(6),
 
выход — Стоп-лосс (1.1%) или Тэйк-профит (3.2%)
3) Группа «SMA3»:
вход, если Close > SMA(18),
 
выход — Close < SMA(18)
Итак, приступим.
Добавляем три параметра в конструктор:
public MyScript()
{
	parameter0 = CreateParameter("Период SMA1 (LE)", 6, 0, 100, 1);
	parameter1 = CreateParameter("Период SMA2 (LE)", 9, 0, 100, 1);
	parameter2 = CreateParameter("Период SMA3 (LE)", 18, 0, 100, 1);
}
Первая группа условий:
// вход в позицию
if (MarketPositionBySignal("SMA1") == 0)
{
	if (Close[bar] > SMA.Value(bar, Close, parameter0.ValueInt))
		BuyAtClose(bar, "SMA1");
}
else if (MarketPositionBySignal("SMA1") == 1)
{
	// Выход из длинной позиции
	if (Close[bar] < SMA.Value(bar, Close, parameter0.ValueInt))
		SellAtClose(bar, GetPositionBySignal("SMA1"), "SMA1");
}
Вторая группа условий:
// вход в позицию
if (MarketPositionBySignal("SMA2") == 0)
{
	if (Close[bar] > SMA.Value(bar, Close, parameter1.ValueInt))
		BuyAtClose(bar, "SMA2");
}
else if (MarketPositionBySignal("SMA2") == 1)
{
	Position p = GetPositionBySignal("SMA2");
	// Выход из длинной позиции
	if (p.NetProfitAsOfBarPercent(bar) < -1.1)
	{
		SellAtClose(bar, p, "SMA2 — SL");
	}
	else if (p.NetProfitAsOfBarPercent(bar) > 3.2)
	{
		SellAtClose(bar, p, "SMA2 — TP");
	}
}
Третья группа условий:
// вход в позицию
if (MarketPositionBySignal("SMA3") == 0)
{
	if (Close[bar] > SMA.Value(bar, Close, parameter2.ValueInt))
		BuyAtClose(bar, "SMA3");
}
else if (MarketPositionBySignal("SMA3") == 1)
{
	// Выход из длинной позиции
	if (Close[bar] < SMA.Value(bar, Close, parameter2.ValueInt))
		SellAtClose(bar, GetPositionBySignal("SMA3"), "SMA3");
}
Как мы видим, используется немного другая логика проверки на текущую активную позицию.
С помощью функции MarketPositionBySignal() мы проверяем, в каком состоянии находится позиция из определенной группы (это аналог функции MarketPosition для однопозиционных стратегий).
С помощью функции GetPositionBySignal() мы получаем активную позицию из определенной группы (аналог функции LastPosition).
Итоговый код
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;
		public MyScript()
		{
			parameter0 = CreateParameter("Период SMA1(LE)", 6, 0, 100, 1);
			parameter1 = CreateParameter("Период SMA2(LE)", 9, 0, 100, 1);
			parameter2 = CreateParameter("Период SMA3(LE)", 18, 0, 100, 1);
		}
		public int MarketPositionBySignal(string signal)
		{
			foreach (Position pos in ActivePositions)
			{
				if (pos.EntrySignal.Contains(signal))
				{
					if (pos.PositionType == PositionType.Long)
						return 1;
					else if (pos.PositionType == PositionType.Short)
						return -1;
				}
			}
			return 0;
		}
		public Position GetPositionBySignal(string signal)
		{
			foreach (Position pos in ActivePositions)
			{
				if (pos.EntrySignal.Contains(signal))
				{
					return pos;
				}
			}
			return null;
		}
		public override void Execute()
		{
			// Вывод индикаторов на график
			PlotSeries(PricePane, SMA.Series(Close, parameter0.ValueInt), Color.Blue, LineStyle.Solid, 1);
			PlotSeries(PricePane, SMA.Series(Close, parameter1.ValueInt), Color.Red, LineStyle.Solid, 1);
			PlotSeries(PricePane, SMA.Series(Close, parameter2.ValueInt), Color.Green, LineStyle.Solid, 1);
			// Основной цикл
			for (int bar = 19; bar < Symbol.Count; bar++)
			{
				// вход в позицию
				if (MarketPositionBySignal("SMA1") == 0)
				{
					if (Close[bar] > SMA.Value(bar, Close, parameter0.ValueInt))
						BuyAtClose(bar, "SMA1");
				}
				else if (MarketPositionBySignal("SMA1") == 1)
				{
					// Выход из длинной позиции
					if (Close[bar] < SMA.Value(bar, Close, parameter0.ValueInt))
						SellAtClose(bar, GetPositionBySignal("SMA1"), "SMA1");
				}
				// вход в позицию
				if (MarketPositionBySignal("SMA2") == 0)
				{
					if (Close[bar] > SMA.Value(bar, Close, parameter1.ValueInt))
						BuyAtClose(bar, "SMA2");
				}
				else if (MarketPositionBySignal("SMA2") == 1)
				{
					Position p = GetPositionBySignal("SMA2");
					// Выход из длинной позиции
					if (p.NetProfitAsOfBarPercent(bar) < -1.1)
					{
						SellAtClose(bar, p, "SMA2 — SL");
					}
					else if (p.NetProfitAsOfBarPercent(bar) > 3.2)
					{
						SellAtClose(bar, p, "SMA2 — TP");
					}
				}
				// вход в позицию
				if (MarketPositionBySignal("SMA3") == 0)
				{
					if (Close[bar] > SMA.Value(bar, Close, parameter2.ValueInt))
						BuyAtClose(bar, "SMA3");
				}
				else if (MarketPositionBySignal("SMA3") == 1)
				{
					// Выход из длинной позиции
					if (Close[bar] < SMA.Value(bar, Close, parameter2.ValueInt))
						SellAtClose(bar, GetPositionBySignal("SMA3"), "SMA3");
				}
			}
		}
	}
}
Результат

