Список форумов AmiSite.ru AmiSite.ru
Форум по Ами
 FAQ  •  Поиск  •  Пользователи  •  Группы   •  Регистрация  •  Профиль  •  Войти и проверить личные сообщения  •  Вход
 Открытие нескольких сделок в одну сторону Следующая тема
Предыдущая тема
Начать новую тему  Ответить на тему
Автор Сообщение
ustas235



Зарегистрирован: 13.03.2016
Сообщения: 5

СообщениеДобавлено: Вс Апр 24, 2016 1:27 pm Ответить с цитатой Вернуться к началу

Добрый день.
Пытаюсь написать стратегию, где будет происходить открытие нескольких сделок в одну сторону, с последовательным их закрытием.
Как я понял АМИ по умолчанию может открывать только одну сделку в одну сторону. Поэтому прошу помощи по двум возможным вариантам:
1. Доливка по существующие позиции. Можно пример кода и необходимые настройки в тестере, если таковые нужны? Просто фраза: "Для этого есть SigScaleIn/SigScaleOut", мне мало о чем говорит. Куда их нужно "прикрутить", чтобы ими пользоваться?
2. Можно разрешить Ами иметь одновременно несколько открытых позиций по одной бумаге. Я добавил строку в коде:
Код:
SetBacktestMode( backtestRegularRawMulti );

и попробовал создать элементарный пример:
Код:
Short[5]=1; Short[30]=1; Short[50]=1;Cover[80]=1;

Данные сделки на графике видны, но при тестированиии открывается только одна сделка, и еще одна левая непонятно откуда взявшаяся:
https://gyazo.com/8ac84210a913027d4c90fee29841953f
Посмотреть профиль Отправить личное сообщение
000
Site Admin


Зарегистрирован: 10.12.2007
Сообщения: 8816

СообщениеДобавлено: Вс Апр 24, 2016 10:25 pm Ответить с цитатой Вернуться к началу

В Ами есть 3 способа открыть несколько сделок по одной бумаге.
1. Использовать SetBacktestMode( backtestRegularRawMulti );
Ты там сделал почти все правильно, но у тебя все деньги ушли в первую сделку. Следует ограничить сайз открываемой позиции, тогда откроются все сделки как и планировальось. Добавь
Код:
SetPositionSize(1, 4);

Тут следует иметь ввиду, что закрыть можно только все позиции сразу.
2. Использовать SigScaleIn/SigScaleOut. В хелпере нормальный пример. И даже не один.
Example 1: dollar-cost averaging (each month you buy stocks for fixed dollar amount)
Код:
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;

Кроме того на форуме 1000000 раз это обсуждали. Воспользуйся поиском по форуму. Если что не поймешь, то тогда задавай конкретные вопросы ибо еще раз описывать как это работает и как использовать чето ломает.
Следует иметь ввиду, что в отчете тестера доливки отливки не отображаются. Отображается только начальное открытие позиции и ее закрытие.
3. Можно создать в базе клоны инструментов и разные сделки проводить на "параллельных" бумагах. Это тут тоже обсуждалось. Можно найти.

_________________
ceterum censeo carthaginem esse delendam
Удачи. Олег.
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
rupiter



Зарегистрирован: 16.09.2013
Сообщения: 73

СообщениеДобавлено: Вт Июл 05, 2016 12:06 pm Ответить с цитатой Вернуться к началу

У меня вопрос в тему. В моей системе предусмотрены два отдельных условия для входа (на разных ценовых уровнях), и вот на одном баре сработали оба эти условия. Мне нужно, чтобы на этом баре произошли два входа на обозначенных уровнях. Возможно ли это сделать?
(По форуму посмотрел, ничего подходящего не нашел).
В интернете попался комментарий Томаша на сходную ситуацию - тот предлагает использовать кастомный бэктестинг. Но, может есть способ по-проще?
Посмотреть профиль Отправить личное сообщение
000
Site Admin


Зарегистрирован: 10.12.2007
Сообщения: 8816

СообщениеДобавлено: Вт Июл 05, 2016 3:36 pm Ответить с цитатой Вернуться к началу

Сделай клон бумаги и торгуй не один, а два символа. Тогда легко можно на одном баре иметь 2 входа по разным ценам.

_________________
ceterum censeo carthaginem esse delendam
Удачи. Олег.
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
rupiter



Зарегистрирован: 16.09.2013
Сообщения: 73

СообщениеДобавлено: Вт Июл 05, 2016 7:31 pm Ответить с цитатой Вернуться к началу

000 писал(а):
Сделай клон бумаги и торгуй не один, а два символа. Тогда легко можно на одном баре иметь 2 входа по разным ценам.

Ну, не знаю. Как вариант, конечно, можно использовать. Но, по-моему, это не выход. Что если мне нужно использовать не два, а десять разных входов? Или если одни входы имеют логическую зависимость с другими? Похоже, все-таки придется углубляться в кастомный бэктестинг...
Посмотреть профиль Отправить личное сообщение
rupiter



Зарегистрирован: 16.09.2013
Сообщения: 73

СообщениеДобавлено: Вс Июл 10, 2016 2:46 pm Ответить с цитатой Вернуться к началу

Решение найдено! (Ну, почти. Почему почти - скажу ниже).

Итак, условия:
Вычисляются уровни для входа в длинную позицию выше рынка:
Код:
Range = High - Low;
ThePivot = ( Low + High + Close ) / 3;
Resistance1 = ( ThePivot * 2 ) - Low;
Resistance2 = ThePivot + Range;
Resistance3 = Resistance1 + Range;

Определяется дополнительный фильтр для входа:
Код:
//Determining market's character
BullMarket = MA( Close, 4 ) > MA( Close, 9 ) and MA( Close, 9 ) > MA( Close, 18 );

Условие для первого входа:
Код:
BullR2 = Cross( High, Ref( Resistance2, -1 ) );


Выход по трейлинг стопу:
Код:
TrailLongStop = Ref( LLV( Low, TrailBar ), -1 );


То есть при пробитии уровня Resistance2 мы входим в длинную позицию одним лотом. Закрываем позицию трейлинг стопом.

Остальные условия я решил прописать внутри кода кастомного тестинга. А именно:
Дополнительный вход при пересечении уровня Resistance3 одним лотом, даже если предыдущий вход произошел на том же баре (как правило, это и происходит).
Код:
if( trade.GetPrice( i, "H" ) >=  enter3[i] AND trade.GetPrice( i - 1, "H" ) < enter3[i] AND trade.Shares < trade.RoundLotSize * 2 )
            {
                bo.RawTextOutput( DateOfBar[i] );
                scaleSize = trade.RoundLotSize * trade.GetPrice( i, "C" );
                bo.ScaleTrade( i, trade.Symbol, True, enter3[i], scaleSize );
            }

Прошу обратить внимание на переменную enter3. Это уровень второго входа. Но так как тестер оперирует портфелем символов, ему нельзя просто передать значение уровня вне контекста конкретного символа. Поэтому был создан отдельный временный символ с требуемым уровнем:
Цитата:
AddToComposite( Ref( Resistance3, -1 ), "~Resistance3_" + Name(), "C", atcFlagDefaults | atcFlagEnableInBacktest );
enter3 = Foreign( "~Resistance3_" + trade.Symbol, "C" );

Дополнительное условие выхода: первое прибыльное открытие:
Код:
if( trade.GetPercentProfit() > 0 )
            {
                bo.RawTextOutput( DateOfBar[i] );
                bo.ExitTrade( i, trade.Handle, trade.GetPrice( i, "O" ) );
            }


Весь код целиком:
Код:
SetOption( "MaxOpenPositions", 1 );
SetPositionSize( RoundLotSize, spsShares );
SetBacktestMode( backtestRegularRaw );
SetOption( "AllowSameBarExit", False );
SetOption( "HoldMinBars", 1 );

TrailBar = 4;

//Calculating pivots, R levels
Range = High - Low;
ThePivot = ( Low + High + Close ) / 3;
Resistance1 = ( ThePivot * 2 ) - Low;
Resistance2 = ThePivot + Range;
Resistance3 = Resistance1 + Range;

//Determining market's character
BullMarket = MA( Close, 4 ) > MA( Close, 9 ) and MA( Close, 9 ) > MA( Close, 18 );

//Long enter condition
BullR2 = Cross( High, Ref( Resistance2, -1 ) );

TrailLongStop = Ref( LLV( Low, TrailBar ), -1 );

Buy = BullR2 AND BullMarket;
BuyPrice = Max( Ref( Resistance2, -1 ), Open );

Sell = Cross( TrailLongStop, Low ) ;
SellPrice = Min( TrailLongStop, Open );

AddToComposite( Ref( Resistance3, -1 ), "~Resistance3_" + Name(), "C", atcFlagDefaults | atcFlagEnableInBacktest );

DateOfBar = DateNum();

SetCustomBacktestProc( "" );

if( Status( "action" ) == actionPortfolio )
{
    bo = GetBacktesterObject();   //  Get backtester object

    bo.PreProcess();   //  Do pre-processing

    for( i = 1; i < BarCount; i++ )   //  Loop through all bars
    {
        bo.UpdateStats( i, 0 );   //  Update MAE/MFE stats for bar

        for( sig = bo.GetFirstSignal( i ); sig; sig = bo.GetNextSignal( i ) )
        {
            //  Loop through all signals at this bar
            bo.RawTextOutput( DateOfBar[i] );

            if( sig.IsEntry() )
                bo.EnterTrade( i, sig.Symbol, sig.IsLong(), sig.Price, sig.PosSize );

            if( sig.IsExit() )
                bo.ExitTrade( i, sig.Symbol, sig.Price );

        }

        bo.HandleStops( i );   //  Handle programmed stops at this bar

        for( trade = bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos() )
        {
            enter3 = Foreign( "~Resistance3_" + trade.Symbol, "C" );


            if( trade.GetPrice( i, "H" ) >=  enter3[i] AND trade.GetPrice( i - 1, "H" ) < enter3[i] AND trade.Shares < trade.RoundLotSize * 2 ) // AND trade.BarsInTrade <= 1 )
            {
                bo.RawTextOutput( DateOfBar[i] );
                scaleSize = trade.RoundLotSize * trade.GetPrice( i, "C" );
                bo.ScaleTrade( i, trade.Symbol, True, enter3[i], scaleSize );
            }

            if( trade.GetPercentProfit() > 0 )
            {
                bo.RawTextOutput( DateOfBar[i] );
                bo.ExitTrade( i, trade.Handle, trade.GetPrice( i, "O" ) );
            }
        }

        bo.UpdateStats( i, 1 );   //  Update MAE/MFE stats for bar
        bo.UpdateStats( i, 2 );   //  Update stats at bar's end
    }   //  End of for loop over bars

    bo.PostProcess();   //  Do post-processing
}

Plot( C, "C", IIf( BullMarket, colorPaleGreen, colorGrey40 ), styleBar, Null, Null, 0, 0, -10 );

Plot( BullR2 AND bullmarket, "BullR2", colorRed, styleHistogram | styleOwnScale );

Plot( Ref( Resistance2, -1 ), "R2", colorGreen );
Plot( Ref( Resistance3, -1 ), "R3", colorBlue );

Plot( TrailLongStop, "TrailLongStop", colorGrey40, styleDashed );
Посмотреть профиль Отправить личное сообщение
rupiter



Зарегистрирован: 16.09.2013
Сообщения: 73

СообщениеДобавлено: Вс Июл 10, 2016 2:57 pm Ответить с цитатой Вернуться к началу

Теперь немного картинок. График с отмеченными уровнями входов по двум уровням на одном баре и выходе на открытии следующего. А также фрагмент detail log, с записями этих входов и выхода.
Посмотреть профиль Отправить личное сообщение
rupiter



Зарегистрирован: 16.09.2013
Сообщения: 73

СообщениеДобавлено: Вс Июл 10, 2016 3:21 pm Ответить с цитатой Вернуться к началу

Некоторые нюансы.

1. Шаблоном low level Амиброкера это не предусмотрено, но если не разместить команду
Код:
bo.UpdateStats( i, 0 );

в начале цикла, то тестирование проходит с ошибками.

2. Detail Log при кастомном бэктестинге имеет вид неприглядный. Поэтому пришлось использовать команду
Код:
bo.RawTextOutput( DateOfBar[i] );

на каждом обработанном сигнале, для отображения дат этих событий.

Теперь, почему найденное решение меня не вполне удовлетворило. Дело в том, что целью было написание входа, который на Easylanguage выглядел так:
Цитата:
buy next bar at Resistance2 stop;
buy next bar at Resistance3 stop;

То есть, открывались две независимые сделки на разных уровнях. В то время, как у меня просто менялся размер позиции, если акция пересекала дополнительный уровень. EL код подразумевал независимое закрытие обеих позиций, а также открытие двух позиций по первому условию (если они происходили на разных барах). У меня же доливка возможна только по второму условию... Понятно, что на AFL можно прописать условия, идентичные условиям, написанным выше на EL, но это уже будет другой код. В любом случае, программа-минимум выполнена: способ отработать два входа на одном баре одного символа найден.
Посмотреть профиль Отправить личное сообщение
000
Site Admin


Зарегистрирован: 10.12.2007
Сообщения: 8816

СообщениеДобавлено: Вс Июл 10, 2016 4:01 pm Ответить с цитатой Вернуться к началу

Вау. Браво!

_________________
ceterum censeo carthaginem esse delendam
Удачи. Олег.
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
rupiter



Зарегистрирован: 16.09.2013
Сообщения: 73

СообщениеДобавлено: Вс Июл 10, 2016 4:25 pm Ответить с цитатой Вернуться к началу

000 писал(а):
Вау. Браво!

Спасибо! Very Happy
Посмотреть профиль Отправить личное сообщение
AlexLan73



Зарегистрирован: 25.06.2012
Сообщения: 87

СообщениеДобавлено: Ср Июл 13, 2016 6:26 pm Ответить с цитатой Вернуться к началу

Спасибо, Вам за проделанную работу. Круто!!!! Shocked Smile Very Happy
Посмотреть профиль Отправить личное сообщение
rupiter



Зарегистрирован: 16.09.2013
Сообщения: 73

СообщениеДобавлено: Чт Июл 14, 2016 5:47 am Ответить с цитатой Вернуться к началу

AlexLan73 писал(а):
Спасибо, Вам за проделанную работу. Круто!!!! Shocked Smile Very Happy
Да не за что! Very Happy На самом деле, мне самому было очень интересно разбираться с этой проблемой. Но, вообще, конечно, тут осталось еще много неясностей - копать и копать Confused
Посмотреть профиль Отправить личное сообщение
trashfx



Зарегистрирован: 27.06.2015
Сообщения: 90

СообщениеДобавлено: Вс Авг 14, 2016 2:35 pm Ответить с цитатой Вернуться к началу

rupiter писал(а):


Дополнительное условие выхода: первое прибыльное открытие:
Код:
if( trade.GetPercentProfit() > 0 )
            {
                bo.RawTextOutput( DateOfBar[i] );
                bo.ExitTrade( i, trade.Handle, trade.GetPrice( i, "O" ) );
            }


Весь код целиком:
Код:
SetOption( "MaxOpenPositions", 1 );
SetPositionSize( RoundLotSize, spsShares );
SetBacktestMode( backtestRegularRaw );
SetOption( "AllowSameBarExit", False );
SetOption( "HoldMinBars", 1 );

TrailBar = 4;

//Calculating pivots, R levels
Range = High - Low;
ThePivot = ( Low + High + Close ) / 3;
Resistance1 = ( ThePivot * 2 ) - Low;
Resistance2 = ThePivot + Range;
Resistance3 = Resistance1 + Range;

//Determining market's character
BullMarket = MA( Close, 4 ) > MA( Close, 9 ) and MA( Close, 9 ) > MA( Close, 18 );

//Long enter condition
BullR2 = Cross( High, Ref( Resistance2, -1 ) );

TrailLongStop = Ref( LLV( Low, TrailBar ), -1 );

Buy = BullR2 AND BullMarket;
BuyPrice = Max( Ref( Resistance2, -1 ), Open );

Sell = Cross( TrailLongStop, Low ) ;
SellPrice = Min( TrailLongStop, Open );

AddToComposite( Ref( Resistance3, -1 ), "~Resistance3_" + Name(), "C", atcFlagDefaults | atcFlagEnableInBacktest );

DateOfBar = DateNum();

SetCustomBacktestProc( "" );

if( Status( "action" ) == actionPortfolio )
{
    bo = GetBacktesterObject();   //  Get backtester object

    bo.PreProcess();   //  Do pre-processing

    for( i = 1; i < BarCount; i++ )   //  Loop through all bars
    {
        bo.UpdateStats( i, 0 );   //  Update MAE/MFE stats for bar

        for( sig = bo.GetFirstSignal( i ); sig; sig = bo.GetNextSignal( i ) )
        {
            //  Loop through all signals at this bar
            bo.RawTextOutput( DateOfBar[i] );

            if( sig.IsEntry() )
                bo.EnterTrade( i, sig.Symbol, sig.IsLong(), sig.Price, sig.PosSize );

            if( sig.IsExit() )
                bo.ExitTrade( i, sig.Symbol, sig.Price );

        }

        bo.HandleStops( i );   //  Handle programmed stops at this bar

        for( trade = bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos() )
        {
            enter3 = Foreign( "~Resistance3_" + trade.Symbol, "C" );


            if( trade.GetPrice( i, "H" ) >=  enter3[i] AND trade.GetPrice( i - 1, "H" ) < enter3[i] AND trade.Shares < trade.RoundLotSize * 2 ) // AND trade.BarsInTrade <= 1 )
            {
                bo.RawTextOutput( DateOfBar[i] );
                scaleSize = trade.RoundLotSize * trade.GetPrice( i, "C" );
                bo.ScaleTrade( i, trade.Symbol, True, enter3[i], scaleSize );
            }

            if( trade.GetPercentProfit() > 0 )
            {
                bo.RawTextOutput( DateOfBar[i] );
                bo.ExitTrade( i, trade.Handle, trade.GetPrice( i, "O" ) );
            }
        }

        bo.UpdateStats( i, 1 );   //  Update MAE/MFE stats for bar
        bo.UpdateStats( i, 2 );   //  Update stats at bar's end
    }   //  End of for loop over bars

    bo.PostProcess();   //  Do post-processing
}

Plot( C, "C", IIf( BullMarket, colorPaleGreen, colorGrey40 ), styleBar, Null, Null, 0, 0, -10 );

Plot( BullR2 AND bullmarket, "BullR2", colorRed, styleHistogram | styleOwnScale );

Plot( Ref( Resistance2, -1 ), "R2", colorGreen );
Plot( Ref( Resistance3, -1 ), "R3", colorBlue );

Plot( TrailLongStop, "TrailLongStop", colorGrey40, styleDashed );



Do not use Addtocomposite and Foreign but Static variables in order to pass from phase 1 to phase 2 because it is faster.

So ...


Код:
StaticVarSet(  "~Resistance3_" + Name(), Ref( Resistance3, -1 )  );


SetCustomBacktestProc( "" );
if( Status( "action" ) == actionPortfolio )
{

     .....

     enter3 = StaticVarGet( "~Resistance3_" + trade.Symbol );

     .....
}
Посмотреть профиль Отправить личное сообщение
rupiter



Зарегистрирован: 16.09.2013
Сообщения: 73

СообщениеДобавлено: Пн Авг 22, 2016 10:14 am Ответить с цитатой Вернуться к началу

trashfx писал(а):


Do not use Addtocomposite and Foreign but Static variables in order to pass from phase 1 to phase 2 because it is faster.

So ...


Код:
StaticVarSet(  "~Resistance3_" + Name(), Ref( Resistance3, -1 )  );


SetCustomBacktestProc( "" );
if( Status( "action" ) == actionPortfolio )
{

     .....

     enter3 = StaticVarGet( "~Resistance3_" + trade.Symbol );

     .....
}

Спасибо, учту.
Посмотреть профиль Отправить личное сообщение
Показать сообщения:      
Начать новую тему  Ответить на тему


 Перейти:   



Следующая тема
Предыдущая тема
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете вкладывать файлы
Вы не можете скачивать файлы


Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme :: Часовой пояс: GMT + 3

File Attachment © by Meik Sievertsen