Пирамидинг в Амиброкере

Часто в алгоритмах возникает необходимость увеличить или уменьшить позицию при выполнении определённых условий. Например, при первом сигнале на вход в позицию она открывается на небольшой объём, потом по мере развития тренда позиция увеличивается. В какой-то момент по достижению первого уровня фиксации ликвидируется часть позиции, при достижении второго уровня - следующая часть и так далее.
Другой вариант - усреднение цены входа путем увеличения позиции при встречном движении рынка (метод мартингейла).
Как реализовать подобные алгоритмы в амиброкере?
Существует стандартный массив PositionSize. Если его заполнить цифрами, равными стоимости контрактов/акций, то в момент появления сигналов Buy, Sell, Short и Cover амиброкер будет соответствующим образом изменять размер своей виртуальной позиции.
Способ прост и довольно удобен, но крайне ограничен. Поэтому разработчиком была реализована стандартная функция SetPositionSize.
СИНТАКСИС | SetPositionSize( size, method ) |
ВОЗВРАЩАЕТ | Массив |
ОПИСАНИЕ | Функция позволяет управлять размером позиции разными способами взависимости от параметра method.
Параметры: size (Массив) описывает требуемый размер позиции method (Массив) задает интерпретацию
Дополнительные возможности (совместимость с PositionSize)
|
Разработчик настоятельно рекомендует использовать механизм SetPositionSize вместо массива SetPosition.
Как применять?
Две специальные константы: sigScaleIn / sigScaleOut. Нужны для того, чтобы рассказать бектестеру, что нужно увеличить или уменьшить позицию
Все что требуется сделать для реализации изменяемого размера позиции, заключается в следующем:
- Задайте переменной BUY / SHORT значение sigScaleIn, если хотите увеличить длинные / короткие позиции
- Задайте переменной BUY / SHORT значение sigScaleOut, если хотите уменьшить длинные / короткие позиции
Масштабирование размера определяется переменной PositionSize, которая в случае масштабирования определяет не абсолютные значения позиции, а их изменение.
ВАЖНО: Обратите внимание, что backtester рассматривает последовательность изменений объема позиций (scale-in/out) как одну сделку (т.е. покажет одну строку в списке сделок бектестера). Единственная разница по сравнению с простой торговлей является то, что он будет рассчитывать среднюю цену входа и выхода. Комиссия, конечно, посчитается правильно, каждое изменение позиции будет сопровождаться комиссионными расходами.
Если вы хотите увидеть информацию о масштабировании можно запустить бэктест в режиме "подробный журнал", и тогда можно детально рассмотреть, как происходит масштабирование и рассчитываются средние цены.
Можно включить подробный режим прямо из скрипта:
SetOption("PortfolioReportMode",1);
Примеры
1. каждый месяц покупаем акции на одну и ту же сумму
FixedDollarAmount = 500;
MonthBegin = Month() != Ref( Month(), -1 );
FirstPurchase = Cum( MonthBegin ) == 1;
Buy = IIf( FirstPurchase, 1, // True (or 1) represents regular buy signal
IIf( MonthBegin, sigScaleIn, // each month increase position
0 ) ); // otherwise no signal
Sell = 0; // we do not sell
PositionSize = FixedDollarAmount;
2. Упрощенная формула, потому что Amibroker рассматривает первый sigScaleIn как Buy в любом случае
FixedDollarAmount = 500;
MonthBegin = Month() != Ref( Month(), -1 );
FirstPurchase = Cum( MonthBegin ) == 1;
Buy = IIf( MonthBegin, sigScaleIn, 0 ); // ежемесячно увеличиваем позицию
Sell = 0; // никогда не продаём
PositionSize = FixedDollarAmount;
3. Увеличение позиции, когда прибыли от торговли без пирамидинга становится больше, чем 5% и уменьшение позиции, когда потери больше, чем 5%
// percent equity change threshold when pyramiding is performedPyramidThreshold = 5;
// regular trading rules (no pyramiding)
Buy = Cross( MACD(), Signal() );
Sell = Cross( Signal(), MACD() );
e = Equity(1); // generate equity without pyramiding effect
PcntProfit = 100 * ( e - ValueWhen( Buy, e ) )/ValueWhen( Buy, e );
InTrade = Flip( Buy, Sell );
// ExRem is used here to ensure that scaling-in/out occurs
// only once since trade entry
DoScaleIn = ExRem( InTrade AND PcntProfit > PyramidThreshold, Sell );
DoScaleOut = ExRem( InTrade AND PcntProfit < -PyramidThreshold, Sell );
// modify rules to handle pyramiding
Buy = Buy + sigScaleIn * DoScaleIn + sigScaleOut * DoScaleOut;
PositionSize = IIf( DoScaleOut, 500, 1000 ); // enter and scale-in size $1000, scale-out size: $500
3. Частичный выход (scaling out) по достижению уровня взятия прибыли. Уменьшается позиция на 50% не первом тейк-уровне и на 50% на втором. По трейлинг стопу закрывается сразу вся позиция
Buy = Cross( MA( C, 10 ), MA( C, 50 ) );Sell = 0;
FirstProfitTarget = 10; // profit
SecondProfitTarget = 20; // in percent
TrailingStop = 10; // also in percent
priceatbuy=0;
highsincebuy = 0;
exit = 0;
for( i = 0; i < BarCount; i++ )
{
if( priceatbuy == 0 AND Buy[ i ] )
{
priceatbuy = BuyPrice[ i ];
}
if( priceatbuy > 0 )
{
highsincebuy = Max( High[ i ], highsincebuy );
if( exit == 0 AND
High[ i ] >= ( 1 + FirstProfitTarget * 0.01 ) * priceatbuy )
{
// first profit target hit - scale-out
exit = 1;
Buy[ i ] = sigScaleOut;
}
if( exit == 1 AND
High[ i ] >= ( 1 + SecondProfitTarget * 0.01 ) * priceatbuy )
{
// second profit target hit - exit
exit = 2;
SellPrice[ i ] = Max( Open[ i ], ( 1 + SecondProfitTarget * 0.01 ) * priceatbuy );
}
if( Low[ i ] <= ( 1 - TrailingStop * 0.01 ) * highsincebuy )
{
// trailing stop hit - exit
exit = 3;
SellPrice[ i ] = Min( Open[ i ], ( 1 - TrailingStop * 0.01 ) * highsincebuy );
}
if( exit >= 2 )
{
Buy[ i ] = 0;
Sell[ i ] = exit + 1; // mark appropriate exit code
exit = 0;
priceatbuy = 0; // reset price
highsincebuy = 0;
}
}
}
SetPositionSize( 50, spsPercentOfEquity );
SetPositionSize( 50, spsPercentOfPosition * ( Buy == sigScaleOut ) ); // scale out 50% of position
Можно ли такие формулы превращать в полноценного робота, выставляющего заявки в соответствии с алгоритмом и изменяя размер позиции? Да, можно. В частности,это можно реализовать с помощью AmiSharp.
Как то так
if( exit == 0 AND High[ i ] >= ( 1 + FirstProfitTarg et * 0.01 ) * priceatbuy )
{
// first profit target hit - scale-out
exit = 1;
Buy[ i ] = sigScaleOut;
BuyPrice[ i ] = ( 1 + FirstProfitTarg et * 0.01 ) * priceatbuy;
}
if( exit == 1 AND High[ i ] >= ( 1 + SecondProfitTar get * 0.01 ) * priceatbuy )
{
// second profit target hit - scale-out
exit = 2;
Buy[ i ] = sigScaleOut;
BuyPrice[ i ] = ( 1 + SecondProfitTar get * 0.01 ) * priceatbuy;
}
Одна свеча один параметр, получается первый уровень будит проигнорирован?
Если да, какой способ применим?
Расширяйте логику. Если сработал Профит 2, значит профит1 тоже должен существовать и его надо исполнять.
RSS лента комментариев этой записи