Автор |
Сообщение |
genom
Зарегистрирован: 09.11.2010
Сообщения: 53
|
Всем здравия!
Занялся созданием портфельных систем, чего ранее не делал. Есть вопрос.
Нужно реализовать следующую схему распределения объема денег при торговле:
- условие: есть несколько торгуемых акций;
вход в сделку происходит в одно и то же время каждый день, закрытие происходит до этого же времени на следующие сутки, т.е. всегда перед входом 100% депо свободно и готово к торговле;
может быть одновременно сигнал на вход по системе в один инструмент, а может быть сразу в несколько (например 8 одновременно и более).
- вопрос: как сделать, что бы весь капитал участвовал в торговле, а именно при наличии сигнала только на одном инструменте задействуется 100% от депо, при наличии 2 и более капитал распределяется равными долями на 2 и более соответственно?
Сколько не мурыжил АФЛ - не смог добиться такого, максимум 100% на каждый инструмент от капитала, хоть вместе, а хоть отдельно ,т.е. автоматом плечи берутся или в дни, где есть несколько сигналов по нескольким инструментам в ход берется только первый на 100%, а остальные пропускаются((((
Прошу Вашей помощи, коллеги! |
|
|
Посмотреть профиль Отправить личное сообщение |
|
000
Site Admin
Зарегистрирован: 10.12.2007
Сообщения: 9106
|
Т.е надо узнать число сигналов и равномерно разделить между ними имеющиеся деньги? |
_________________ ceterum censeo carthaginem esse delendam
Удачи. Олег. |
|
Посмотреть профиль Отправить личное сообщение Посетить сайт автора |
|
genom
Зарегистрирован: 09.11.2010
Сообщения: 53
|
000 писал(а): |
Т.е надо узнать число сигналов и равномерно разделить между ними имеющиеся деньги? |
Все верно, именно так получается. |
|
|
Посмотреть профиль Отправить личное сообщение |
|
000
Site Admin
Зарегистрирован: 10.12.2007
Сообщения: 9106
|
Тут самое дело воспользоваться продвинутым управлением портфельным тестером.
В общем к системе надо добавить типа такого.
Код: |
SetOption("UseCustomBacktestProc", True);
if(Status("action") == actionPortfolio)
{
bo = GetBacktesterObject();
bo.PreProcess();
NumSig = 0;
for(bar = 0; bar < BarCount; bar++)
{
CurrentPortEquity = bo.Equity;
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // считаем сигналы на вход на этом баре
{
if( sig.IsEntry() )
{
NumSig++;
}
}
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // задаем сайз сигналам
{
sig.PositionSize = int(-100/NumSig);
}
bo.ProcessTradeSignals(bar);
}
bo.PostProcess;
} |
Правда я не проверял, но вроде все правильно.
Почитать можно в хелпере
Porfolio Backtester Interface Reference Guide
еще тут
http://www.amibroker.com/docs/Houston2.pdf
и тут
http://www.amibroker.com/kb/category/afl/custom-backtest/ |
_________________ ceterum censeo carthaginem esse delendam
Удачи. Олег. |
|
Посмотреть профиль Отправить личное сообщение Посетить сайт автора |
|
genom
Зарегистрирован: 09.11.2010
Сообщения: 53
|
Спасибо за оперативность. Поставил в код, в конце тестирования выдало:
}
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // задаем сайз сигналам
{
sig.PositionSize = int(-100/NumSig)
-------------------------------------------^
Error 20.
COM method/function `PositionSize` does not exist |
|
|
Посмотреть профиль Отправить личное сообщение |
|
000
Site Admin
Зарегистрирован: 10.12.2007
Сообщения: 9106
|
Угу. Разумеется такой функции нет. Надо PosSize |
_________________ ceterum censeo carthaginem esse delendam
Удачи. Олег. |
|
Посмотреть профиль Отправить личное сообщение Посетить сайт автора |
|
genom
Зарегистрирован: 09.11.2010
Сообщения: 53
|
Протестил, код пошел, но теперь: первый день - 1 покупка (1 сигнал был) на 100% капитала примерно; второй день - 2 сигнала было и примерно по 33% на каждый инструмент, т.е. 2/3 капитала задействовало; третий день примерно на 30% один сигнал был и т.д. в итоге в конце на 1 процент от капитала покупка идет.
Понижение с каждой сделкой. Что то в коде понижает сайз с каждым трейдом. |
|
|
Посмотреть профиль Отправить личное сообщение |
|
000
Site Admin
Зарегистрирован: 10.12.2007
Сообщения: 9106
|
Ага. Не правильно считаю сигналы. Надо на каждом новом баре обнулять переменную NumSig.
Я написал и не проверил, а этой темой владею не очень
Код: |
SetOption("UseCustomBacktestProc", True);
if(Status("action") == actionPortfolio)
{
bo = GetBacktesterObject();
bo.PreProcess();
for(bar = 0; bar < BarCount; bar++)
{
NumSig = 0;
CurrentPortEquity = bo.Equity;
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // считаем сигналы на вход на этом баре
{
if( sig.IsEntry() )
{
NumSig++;
}
}
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // задаем сайз сигналам
{
sig.PosSize = int(-100/NumSig);
}
bo.ProcessTradeSignals(bar);
}
bo.PostProcess;
} |
|
_________________ ceterum censeo carthaginem esse delendam
Удачи. Олег.
Последний раз редактировалось: 000 (Чт Май 28, 2015 11:06 pm), всего редактировалось 1 раз |
|
Посмотреть профиль Отправить личное сообщение Посетить сайт автора |
|
genom
Зарегистрирован: 09.11.2010
Сообщения: 53
|
Ура! Работает как и задумывалось. Не прибедняйся в своих знаниях, я вообще ноль в CBI. Благодарю |
|
|
Посмотреть профиль Отправить личное сообщение |
|
genom
Зарегистрирован: 09.11.2010
Сообщения: 53
|
Олег! А как к этому коду прикрутить проверку на объем, т.е.
предположим поступило 10 сигналов одновременно, продвинутый портфельный тестер разделил капитал на 10 частей (что уже заложено в коде) и дополнительно проверил каждый инструмент по объему примерно так:
Код: |
e = Equity(); // расчет капитала перед сделками, т.е. здесь "е" должна быть той частью капитала, которая рассчитана от числа сигналов на вход
f = Avg * Volume; // расчет объема в деньгах для каждого инструмента, где сигнал (пересчет из числа акций в деньги)
VolumeCond = IIf( (10 * e) <= f, 1, 0 ); // условие по объему для каждого инструмента по сигналу |
если инструмент не удовлетворяет условию, то его не торгуем, высвобожденный остаток денег разбрасываем (если это возможно) или просто резервируем. т.е. тупо не торгуем на них (можно присвоить торгуемые средства как 0 и сделка не пройдет). |
|
|
Посмотреть профиль Отправить личное сообщение |
|
000
Site Admin
Зарегистрирован: 10.12.2007
Сообщения: 9106
|
Тебе надо в коде системы создать статическую переменную (массив) в которую записать значение
f = Avg * Volume;
StaticVarSet( Name() + "F", f);
Тогда эти значения можно будет использовать в Custom backtester interface
Наверное так
Код: |
SetOption("UseCustomBacktestProc", True);
if(Status("action") == actionPortfolio)
{
bo = GetBacktesterObject();
bo.PreProcess();
for(bar = 0; bar < BarCount; bar++)
{
NumSig = 0;
NumSigF = 0;
CurrentPortEquity = bo.Equity;
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // считаем сигналы на вход на этом баре
{
if( sig.IsEntry() )
{
NumSig++;
}
}
CE = CurrentPortEquity/NumSig; // доля доступного капитала на каждый сигнал
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // отфильтровываем сигналы по объему
{
if(10*CE <= Lookup(StaticVarGet( trade.Symbol + "f"), sig.EntryDateTime))
{
NumSigF++; // считаем сигналы которые проходят
}
}
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // задаем сайз сигналам
{
if(10*CE <= Lookup(StaticVarGet( trade.Symbol + "f"), sig.EntryDateTime))
{
sig.PosSize = int(-100/NumSigF);
}
else
{
sig.PosSize = 0;
}
}
bo.ProcessTradeSignals(bar);
}
bo.PostProcess;
}
f = Avg * Volume;
StaticVarSet( Name() + "f", f );
|
|
_________________ ceterum censeo carthaginem esse delendam
Удачи. Олег. |
|
Посмотреть профиль Отправить личное сообщение Посетить сайт автора |
|
genom
Зарегистрирован: 09.11.2010
Сообщения: 53
|
Вау, круто, спасибо. Вставил, протестил и получил несколько ошибок в конце:
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // отфильтровываем сигналы по объему
{
if(10*CE <= Lookup(StaticVarGet( trade.Symbol +
-------------------------------------------------------^
Error 18.
COM object variable is not initialized or has invalid type (valid COM object handle required)
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // отфильтровываем сигналы по объему
{
if(10*CE <= Lookup(StaticVarGet( trade.Symbol + "
---------------------------------------------------------^
Error 1.
Operation not allowed. Operator/operand type mismatch.
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // отфильтровываем сигналы по объему
{
if(10*CE <= Lookup(StaticVarGet( trade.Symbol + "
---------------------------------------------------------^
Error 5.
Argument `#1` has incorrect type (the function expects different argument type here)
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // отфильтровываем сигналы по объему
{
if(10*CE <= Lookup(StaticVarGet( trade.Symbol + "f"), sig.EntryDateTime)
--------------------------------------------------------------------------------^
Error 20.
COM method/function `EntryDateTime` does not exist
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // задаем сайз сигналам
{
if(10*CE <= Lookup(StaticVarGet( trade.Symbol +
-------------------------------------------------------^
Error 18.
COM object variable is not initialized or has invalid type (valid COM object handle required)
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // задаем сайз сигналам
{
if(10*CE <= Lookup(StaticVarGet( trade.Symbol + "
---------------------------------------------------------^
Error 1.
Operation not allowed. Operator/operand type mismatch.
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // задаем сайз сигналам
{
if(10*CE <= Lookup(StaticVarGet( trade.Symbol + "
---------------------------------------------------------^
Error 5.
Argument `#1` has incorrect type (the function expects different argument type here)
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // задаем сайз сигналам
{
if(10*CE <= Lookup(StaticVarGet( trade.Symbol + "f"), sig.EntryDateTime)
--------------------------------------------------------------------------------^
Error 20.
COM method/function `EntryDateTime` does not exist |
|
|
Посмотреть профиль Отправить личное сообщение |
|
000
Site Admin
Зарегистрирован: 10.12.2007
Сообщения: 9106
|
А так?
Код: |
SetOption("UseCustomBacktestProc", True);
if(Status("action") == actionPortfolio)
{
bo = GetBacktesterObject();
bo.PreProcess();
for(bar = 0; bar < BarCount; bar++)
{
NumSig = 0;
NumSigF = 0;
CurrentPortEquity = bo.Equity;
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // считаем сигналы на вход на этом баре
{
if( sig.IsEntry() )
{
NumSig++;
}
}
CE = CurrentPortEquity/NumSig; // доля доступного капитала на каждый сигнал
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // отфильтровываем сигналы по объему
{
sumb = StaticVarGet( trade.Symbol + "f");
if(10*CE <= Lookup(sumb, sig.EntryDateTime))
{
NumSigF++; // считаем сигналы которые проходят
}
}
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // задаем сайз сигналам
{
sumb = StaticVarGet( trade.Symbol + "f");
if(10*CE <= Lookup(sumb, sig.EntryDateTime))
{
sig.PosSize = int(-100/NumSigF);
}
else
{
sig.PosSize = 0;
}
}
bo.ProcessTradeSignals(bar);
}
bo.PostProcess;
}
f = Avg * Volume;
StaticVarSet( Name() + "f", f );
|
|
_________________ ceterum censeo carthaginem esse delendam
Удачи. Олег. |
|
Посмотреть профиль Отправить личное сообщение Посетить сайт автора |
|
genom
Зарегистрирован: 09.11.2010
Сообщения: 53
|
Теперь вот так (вроде то же самое)
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // отфильтровываем сигналы по объему
{
sumb = StaticVarGet( trade.Symbol +
-------------------------------------------^
Error 18.
COM object variable is not initialized or has invalid type (valid COM object handle required)
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // отфильтровываем сигналы по объему
{
sumb = StaticVarGet( trade.Symbol + "
---------------------------------------------^
Error 1.
Operation not allowed. Operator/operand type mismatch.
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // отфильтровываем сигналы по объему
{
sumb = StaticVarGet( trade.Symbol + "
---------------------------------------------^
Error 5.
Argument `#1` has incorrect type (the function expects different argument type here)
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // отфильтровываем сигналы по объему
{
sumb = StaticVarGet( trade.Symbol + "f");
if(10*CE <= Lookup(sumb, sig.EntryDateTime)
---------------------------------------------------^
Error 20.
COM method/function `EntryDateTime` does not exist
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // задаем сайз сигналам
{
sumb = StaticVarGet( trade.Symbol +
-------------------------------------------^
Error 18.
COM object variable is not initialized or has invalid type (valid COM object handle required)
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // задаем сайз сигналам
{
sumb = StaticVarGet( trade.Symbol + "
---------------------------------------------^
Error 1.
Operation not allowed. Operator/operand type mismatch.
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // задаем сайз сигналам
{
sumb = StaticVarGet( trade.Symbol + "
---------------------------------------------^
Error 5.
Argument `#1` has incorrect type (the function expects different argument type here)
for(sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) // задаем сайз сигналам
{
sumb = StaticVarGet( trade.Symbol + "f");
if(10*CE <= Lookup(sumb, sig.EntryDateTime)
---------------------------------------------------^
Error 20.
COM method/function `EntryDateTime` does not exist |
|
|
Посмотреть профиль Отправить личное сообщение |
|
000
Site Admin
Зарегистрирован: 10.12.2007
Сообщения: 9106
|
Странно. А у тебя версия Ами какая? |
_________________ ceterum censeo carthaginem esse delendam
Удачи. Олег. |
|
Посмотреть профиль Отправить личное сообщение Посетить сайт автора |
|
|