Возможности MATLAB для разработки и тестирования механических торговых систем

Возможности MATLAB для разработки и тестирования механических торговых систем

537
ПОДЕЛИТЬСЯ

объясню почему пакете MATLAB. Я думаю, чтоб оправдать необходимость кропотливого тестирования и подбора характеристик торговых стратегий не нужно лучше…
MetaTrader имеет встроенную систему тестирования и опции торговых стратегий, что дозволяет запускать стратегию на данном участке истории и поглядеть на результаты торговли как графически, так и в виде плит с чертами эффективности данной стратегии в данной части рассказа. Как это смотрится для стратегий Нова, см. ниже.

На мой взор, эта система тестирования владеет рядом недочетов:
1) Не применять настоящие тиковые данные, они могут быть применены лишь в хранимых на сервере данных минут, 5 минут, 15 минут и т. д. временных периодов;
2) Для выбора хорошей стратегии достаточно скудный набор характеристик имеющихся оптимизационных процедур;
3) незначительно наиболее различным, но все же отсутствие набора мотивированных индикаторов торговые стратегии, которые могут быть оптимизированы;
4) среда разработки торговой стратегии, пригодные для малого программирования, не впечатляющее обилие способностей и инструментов.
Но я желал бы быть в состоянии применять клеща (либо по последней мере каждый 2-ой) данные для моделирования торговой ситуациях, создавать торговые стратегии на любом уровне трудности математического описания собственных критериев оценки свойства стратегии, находить рациональные характеристики разных оптимизационных процедур и др.
Все это может быть при использовании программы MATLAB в качестве платформы разработки и тестирования стратегий. Потом Метатрейдер будет по-прежнему употребляться для работы с торговая стратегия, которая реализуется, к примеру, в виде dll, но все более творческой частью сотворения системы будет происходить в наиболее математической среде. Из MetaTrader мы необходимы начальные данные (в моем примере: каждую секунду в текущих ценах на 27 денежных пар).
Данные собираются с помощью пользовательского индикатора в mql4 код, который смотрится приблизительно так:
Всего колонн в 2 раза больше, чем в отчетности денежных пар. //+——————————————————————+
//| pack_collector.mq4 и |
//| Авторского Права 2014, JamaGava |
//| |
//+——————————————————————+
#недвижимость копирайты «Copyright 2014, JamaGava»
#недвижимость ссылку «»
#недвижимость версия «1.00»
#недвижимость серьезный

инт filehandleData;
инт filehandleHead;
инт filehandleVolHead;
инт filehandleVolData;

//+——————————————————————+
//| Функция инициализации профессионала |
//+——————————————————————+
int в функции oninit()
{
EventSetTimer(1);
filehandleData = открытии файлов (fileopen («tickPack.в CSV»,раз file_write|FILE_CSV);
filehandleHead = открытии файлов (fileopen («tickPackHead.в CSV»,раз file_write|FILE_CSV);
filehandleVolHead = открытии файлов (fileopen («tickPackVolumeHead.в CSV»,раз file_write|FILE_CSV);
filehandleVolData = открытии файлов (fileopen («tickPackVolume.в CSV»,раз file_write|FILE_CSV);

FileWrite(filehandleHead,

«ставка:австралийский бакс/бакс США», «спросите:австралийский бакс/бакс США»,
«ставка:евро/бакс», «спросите:» евро/бакс»,
«ставка:пара английский фунт/бакс», «спросите:» фунт/бакс»,
«ставка:бакс/бакс США», «спросите:новозеландский бакс против бакса США»,
«ставка:бакс США/канадский бакс», «спросите:пара USD/CAD в»,
«ставка:USD/СHF», «спросите:» бакс/Франк»,
«ставка:долл/йена», «спросите:пара USD/JPY в»,
«ставка:пара AUD/CAD в», «спросите:пара AUD/CAD в»,
«ставка:пара AUD/CHF в», «спросите:пара AUD/CHF в»,
«ставка:пара AUD/NZD в», «спросите:пара AUD/NZD в»,
«ставка:САПР/ХСН», «спросите:САПР/ХСН»,
«ставка:евро/ауд», «спросите: «туды»,
«ставка:евро/бакс», «спросите:» евро/бакс»,
«ставка:евро/Франк», «спросите:евро/Франк»,
«ставка:евро/фунт стерлингов», «спросите:» евро/фунт»,
«ставка:евро/новозеландский бакс», «спросите:» евро/бакс»,
«ставка:пара GBP/AUD в», «спросите:пара GBP/AUD в»,
«ставка:пара GBP/САПР», «спросите:пара GBP/САПР»,
«ставка:пара GBP/CHF в», «спросите:пара GBP/CHF в»,
«ставка:пара GBP/NZD в», «спросите:пара GBP/NZD в»,
«ставка:пара NZD/CAD в», «спросите:пара NZD/CAD в»,
«ставка:пара NZD/CHF в», «спросите:пара NZD/CHF в»,
«ставка:пара AUD/JPY в», «спросите:пара AUD/JPY в»,
«ставка:САПР (CAD/JPY в», «спросите:САПР (CAD/JPY в»,
«ставка:по CHF/JPY в», «задать:по CHF/JPY в»,
«ставка:евро/йена», «задать паре евро/йена»,
«ставка:фунт/йена», «спросите:фунт/йена»,
«ставка:пара NZD/JPY в», «спросите:пара NZD/JPY в»

);

FileWrite(filehandleVolHead,

«размер:ауд/долл.»,
«размер:евро/бакс»,
«размер:фунт/бакс»,
«размер:новозеландский бакс против бакса США»,
«размер:бакс США/канадский бакс»,
«размер:USD/СHF»,
«размер:денежная пара бакс/йена»,
«размер:ауд/КАД»,
«размер:денежная пара AUD/CHF в»,
«размер:денежная пара AUD/NZD в»,
«размер:САПР/ХСН»,
«размер:евро/ауд»,
«размер:евро/бакс»,
«размер:евро/Франк»,
«размер:пара евро/Франк»,
«размер:евро/новозеландский бакс»,
«размер:пара GBP/AUD в»,
«размер:пара GBP/САПР»,
«размер:фунтов стерлингов/швейцарских франков»,
«размер:пара GBP/NZD в»,
«размер:новозеландский бакс/бакс»,
«размер:пара NZD/CHF в»,
«размер:ауд/йена»,
«размер:САПР (CAD/JPY в»,
«громкость:от CHF/JPY в»,
«размер:евро/йена»,
«размер:фунт/йена»,
«размер:пара NZD/JPY в»

);
FileClose(filehandleHead);
FileClose(filehandleVolHead);
возвращение(INIT_SUCCEEDED);
}

//+——————————————————————+
//| Функция деинициализации профессионала |
//+——————————————————————+
пустоту функции ondeinit(const и инт причина)
{
EventKillTimer();
FileClose(filehandleData);
}

//+——————————————————————+
//| Функция таймера |
//+——————————————————————+
пустота таймера ontimer()
{
FileWrite(filehandleData,
MarketInfo(«австралиец», MODE_BID), MarketInfo(«австралиец», MODE_ASK),
MarketInfo(«паре EURUSD», MODE_BID), MarketInfo (пары EURUSD», MODE_ASK),
MarketInfo(«пара GBPUSD», MODE_BID), MarketInfo(«пара GBPUSD», MODE_ASK),
MarketInfo(«пара GBPUSD», MODE_BID), MarketInfo(«пара GBPUSD», MODE_ASK),
MarketInfo(«по EURUSD», MODE_BID), MarketInfo(«по EURUSD», MODE_ASK),
MarketInfo(«usdchf курс», MODE_BID), MarketInfo(«usdchf курс», MODE_ASK),
MarketInfo(«usdjpy и», MODE_BID), MarketInfo(«usdjpy и», MODE_ASK),
MarketInfo(«парах audcad», MODE_BID), MarketInfo(«парах audcad», MODE_ASK),
MarketInfo(«audchf курс», MODE_BID), MarketInfo(«audchf курс», MODE_ASK),
MarketInfo(«пары audnzd», MODE_BID), MarketInfo(«пары audnzd», MODE_ASK),
MarketInfo(«по usdjpy», MODE_BID), MarketInfo(«по usdjpy», MODE_ASK),
MarketInfo(«по euraud», MODE_BID), MarketInfo(«пара audjpy», MODE_ASK),
MarketInfo(«EURCAD», MODE_BID), MarketInfo(«EURCAD», MODE_ASK),
MarketInfo(«денежная пара eurchf», MODE_BID), MarketInfo(«денежная пара eurchf», MODE_ASK),
MarketInfo(«по EURUSD», MODE_BID), MarketInfo(«по EURUSD», MODE_ASK),
MarketInfo(«usdjpy и», MODE_BID), MarketInfo(«usdjpy и», MODE_ASK),
MarketInfo(«GBPAUD», MODE_BID), MarketInfo(«GBPAUD», MODE_ASK),
MarketInfo(«usdjpy и», MODE_BID), MarketInfo(«usdjpy и», MODE_ASK),
MarketInfo(«usdjpy и», MODE_BID), MarketInfo(«usdjpy и», MODE_ASK),
MarketInfo(«GBPNZD», MODE_BID), MarketInfo(«GBPNZD», MODE_ASK),
MarketInfo(«NZDCAD», MODE_BID), MarketInfo(«NZDCAD», MODE_ASK),
MarketInfo(«NZDCHF», MODE_BID), MarketInfo(«NZDCHF», MODE_ASK),
MarketInfo(«usdjpy и», MODE_BID), MarketInfo(«пара audjpy», MODE_ASK),
MarketInfo(«по EURUSD», MODE_BID), MarketInfo(«по EURUSD», MODE_ASK),
MarketInfo(«по chfjpy», MODE_BID), MarketInfo(«по chfjpy», MODE_ASK),
MarketInfo(«eurjpy в», MODE_BID), MarketInfo(«eurjpy в», MODE_ASK),
MarketInfo(«по EURUSD», MODE_BID), MarketInfo(«по EURUSD», MODE_ASK),
MarketInfo(«NZDJPY», MODE_BID), MarketInfo(«NZDJPY», MODE_ASK)
);

FileWrite(filehandleVolData,
iVolume(«паре EURUSD», PERIOD_H1,0),
iVolume(«паре EURUSD», PERIOD_H1,0),
iVolume(«GBPUSD фунт», PERIOD_H1,0),
iVolume(«НОВОЗЕЛАНДЕЦ», PERIOD_H1,0),
iVolume(«паре EURUSD», PERIOD_H1,0),
iVolume(«паре usdchf», PERIOD_H1,0),
iVolume(«пара usdjpy», PERIOD_H1,0),
iVolume(«парах audcad», PERIOD_H1,0),
iVolume(«audchf курс», PERIOD_H1,0),
iVolume(«пары audnzd», PERIOD_H1,0),
iVolume(«по usdjpy», PERIOD_H1,0),
iVolume(«по usdchf», PERIOD_H1,0),
iVolume(«EURCAD», PERIOD_H1,0),
iVolume(«денежная пара eurchf», PERIOD_H1,0),
iVolume(«по EURUSD», PERIOD_H1,0),
iVolume(«пара usdjpy», PERIOD_H1,0),
iVolume(«GBPAUD», PERIOD_H1,0),
iVolume(«пара usdjpy», PERIOD_H1,0),
iVolume(«пара usdjpy», PERIOD_H1,0),
iVolume(«GBPNZD», PERIOD_H1,0),
iVolume(«NZDCAD», PERIOD_H1,0),
iVolume(«NZDCHF», PERIOD_H1,0),
iVolume(«пара usdjpy», PERIOD_H1,0),
iVolume(«по EURUSD», PERIOD_H1,0),
iVolume(«по chfjpy», PERIOD_H1,0),
iVolume(«пара usdjpy», PERIOD_H1,0),
iVolume(«по EURUSD», PERIOD_H1,0),
iVolume(«NZDJPY», PERIOD_H1,0)
);

}
//+——————————————————————+

Таковым образом, данные, собранные и сохраненные в формате CSV файлы. В строчки, написанные цитаты, в столбцы: весь количество bid и ask котировки по каждой денежной паре.
д. К примеру, у нас нет способности держать комп под управлением платформы MetaTrader безпрерывно, потом данные будут поступать единицы: Загрузил, закрыл програмку, переименовал файл, чтоб не переустановите, перезагрузки, и т.
В MATLAB загрузить их последующим образом: Потому вы должны признать, что все массивы с блоками данных различного размера. На данный момент, я собрал данные за 16 недель. Не считая того, данные Размеры различные из-за того, что сбор начался «где-то в первой половине дня в пн и заканчивалась в пятницу, «опосля обеда».
Сценарий loadPrices.м:
глобальных цен;
Н = 16;

Цен = клеточку( N, 1 );

fNames = {
‘C:matlabR2008a_winworkfrxDATA1tickPack.csv’;
‘C:matlabR2008a_winworkfrxDATA2tickPack.csv’;
‘C:matlabR2008a_winworkfrxDATA3tickPack.csv’;
‘C:matlabR2008a_winworkfrxDATA4tickPack.csv’;
‘C:matlabR2008a_winworkfrxDATA5tickPack.csv’;
‘C:matlabR2008a_winworkfrxDATA6tickPack.csv’;
‘C:matlabR2008a_winworkfrxDATA7tickPack.csv’;
‘C:matlabR2008a_winworkfrxDATA8tickPack.csv’;
‘C:matlabR2008a_winworkfrxDATA9tickPack.csv’;
‘C:matlabR2008a_winworkfrxDATA10tickPack.csv’;
‘C:matlabR2008a_winworkfrxDATA11tickPack.csv’;
‘C:matlabR2008a_winworkfrxDATA12tickPack.csv’;
‘C:matlabR2008a_winworkfrxDATA13tickPack.csv’;
‘C:matlabR2008a_winworkfrxDATA14tickPack.csv’;
‘C:matlabR2008a_winworkfrxDATA15tickPack.csv’;
‘C:matlabR2008a_winworkfrxDATA16tickPack.csv’;
};

для я = 1:Н
Цены{ я } = перегрузка( fNames{ я } );
экран( я );
конец

В конце концов, все блоки данных, хранящиеся в глобальной переменной цены, что составляет 16 ячеек.
В реализации стратегии, на каждом закрытия сделки корректируется глобальные переменные, которые охарактеризовывают качество работы стратегии. Все начальные данные передаются через глобальные переменные. Чтоб улучшить эти свойства делают «оболочку», в рамках которой глобальные переменные инициализируются, выберите, какой из характеристик стратегии будут возвращены в качестве параметра, и, по сущности, именуется стратегией. Итак, основная мысль: в стратегии должны быть сделаны таковым образом, что на вход они принимают лишь свои характеристики.
Сценарий testStrat.м:
‘ProfitFactor’, ProfitFactor, … ‘Восстановление’, Восстановления, … ‘ProfitMean’, ProfitMean, … ‘ProfitDealsNumber’, ProfitDealsNumber, … );

конец

Имя скрипта, который реализует стратегию, передается через глобальную переменную stratName. ‘LossMean’, LossMean … Свойства стратегии, которые будут возвращены определяется переменной returnParamIndex раз значение равно 0, то возвращает все свойства в структуре. ‘DealsSigma’, DealsSigma, … ‘Просадка’, Просадки, … ‘Резкий’, Острый, … ‘LossDealsNumber’, LossDealsNumber, … ‘LossDealsRate’, LossDealsRate, … ‘MeanDeal’, MeanDeal, … «Справедливость», Справедливость, … ‘ProfitDealsRate’, ProfitDealsRate, … ‘DealsNumber’, DealsNumber, … функция [Р] = testStrat( П )

глобальные просадки;
восстановление мировой экономики;
глобальной справедливости;
глобальные DealsNumber;
глобальные MeanDeal;
глобальные DealsSigma;
глобальные острый;
глобальные ProfitFactor;
глобальные ProfitDealsNumber;
глобальные ProfitDealsRate;
глобальные ProfitMean;
глобальные LossDealsNumber;
глобальные LossDealsRate;
глобальные LossMean;

глобальные returnParamIndex;

глобальные stratName;

initRates( 0 );

feval( stratName, Р );

переключатель( returnParamIndex )
корпус 1
Р = Просадка;

корпус 2
R = Восстановление;

корпус 3
Р = Капитал;

корпус 4
Р = -DealsNumber;

корпус 5
Р = -MeanDeal;

корпус 6
Р = DealsSigma;

корпус 7
Р = Острый;

корпус 8
Р = ProfitFactor;

корпус 9
Р = -ProfitDealsNumber;

корпус 10
Р = -ProfitDealsRate;

корпус 11
Р = -ProfitMean;

вариант на 12
Р = LossDealsNumber;

корпус 13
Р = LossDealsRate;

корпус 14
Р = LossMean;

вариант 0
Р = структура( …
Обратите внимание, что все значения являются «чем больше, тем лучше» издержки-минус, это изготовлено для универсализации оптимизация-это постоянно минимизация мотивированной параметр.
На самом деле, черт системы:
Просадка — наибольшая просадка (наибольшая разница меж предшествующим максимумом и текущим значением);
Восстановление — фактор восстановления (отношение конечного выиграть наибольшая просадка);
Справедливость — итоговый выигрыш;
DealsNumber — количество сделок;
MeanDeal — средний доход по сделке;
DealsSigma-обычное отклонение дохода по каждой сделки от среднего значения;
Компания Sharp является коэффициент Шарпа (отношение среднего дохода по сделке, чтоб обычное отклонение дохода по операциям от средней);
ProfitFactor — профит-фактор (отношение общей прибыли к полной утраты);
ProfitDealsNumber — количество выигрышных сделок;
ProfitDealsRate — процент выигрышных сделок;
ProfitMean — среднее усиление (удачные сделки);
LossDealsNumber — количество убыточных сделок;
LossDealsRate — процент убыточных сделок;
LossMean — средний убыток на одну убыточную сделку).
Эти индикаторы инициализируются функцией initRates.м
Для чего для вас нехороший инициализации, будет показано ниже, при рассмотрении определенной стратегии. функция к [Z] = initRates( режим )

глобальные просадки;
восстановление мировой экономики;
глобальной справедливости;
глобальные DealsNumber;
глобальные MeanDeal;
глобальные DealsSigma;
глобальные острый;
глобальные ProfitFactor;
глобальные ProfitDealsNumber;
глобальные ProfitDealsRate;
глобальные ProfitMean;
глобальные LossDealsNumber;
глобальные LossDealsRate;
глобальные LossMean;

глобальные maxEquity;
глобальные dealSqr;
глобальные totalProfit;
глобальные totalLoss;

Z с = режим;

maxEquity = 0;
dealSqr = 0;
totalProfit = 0;
totalLoss = 0;

раз Mode == 0

Просадка = 0;
Восстановление = 0;
Эквити = 0;
DealsNumber = 0;
MeanDeal = 0;
DealsSigma = 0;
Шарп = 0;
ProfitFactor = 0;
ProfitDealsNumber = 0;
ProfitDealsRate = 0;
ProfitMean = 0;
LossDealsNumber = 0;
LossDealsRate = 0;
LossMean = 0;

еще

Просадка = 1000;
Восстановление = -1000;
Капитал = -1000;
DealsNumber = 0;
MeanDeal = -1000;
DealsSigma = 1000;
Острые = -1000;
ProfitFactor = 0;
ProfitDealsNumber = 0;
ProfitDealsRate = 0;
ProfitMean = 0;
LossDealsNumber = 100000;
LossDealsRate = 1000;
LossMean = 1000;

конец

Не считая того, может analiziruetsya как 0, так и очевидно нехорошие значения (определяется входным параметром). Обратите внимание, что инициализирует несколько вспомогательных переменных:

maxEquity, dealSqr, totalProfit, totalLoss,
которые употребляются в последующем листинге.
В реализации стратегии, на каждом закрытия сделки, обновит производительность стратегии. Для этого мы используем функцию updateStratRates.м:
функция к [Z] = updateStratRates( dealResult )

для Z = символ( dealResult );

глобальные просадки;
восстановление мировой экономики;
глобальной справедливости;
глобальные DealsNumber;
глобальные MeanDeal;
глобальные DealsSigma;
глобальные острый;
глобальные ProfitFactor;
глобальные ProfitDealsNumber;
глобальные ProfitDealsRate;
глобальные ProfitMean;
глобальные LossDealsNumber;
глобальные LossDealsRate;
глобальные LossMean;

глобальные maxEquity;
глобальные dealSqr;
глобальные totalProfit;
глобальные totalLoss;

Капитал = капитал + dealResult;

раз Эквити > maxEquity
maxEquity = капитал;
конец

вниз = maxEquity капитал;
раз вниз > просадка
Просадка = вниз;
конец

Восстановление = Капитал / Просадки;

DealsNumber = DealsNumber + 1;
MeanDeal = Капитал / DealsNumber;
dealSqr = dealSqr + dealResult^2;
DealsSigma = корень из( (dealSqr / DealsNumber) — MeanDeal^2 );
Острые = MeanDeal / DealsSigma;

раз dealResult > 0
ProfitDealsNumber = ProfitDealsNumber + 1;
totalProfit = totalProfit + dealResult;
ProfitMean = totalProfit / ProfitDealsNumber;
еще
LossDealsNumber = LossDealsNumber + 1;
totalLoss = totalLoss + dealResult;
LossMean = totalLoss / LossDealsNumber;
конец

ProfitFactor = -totalProfit / totalLoss;
ProfitDealsRate = ProfitDealsNumber / DealsNumber;
LossDealsRate = 1 — ProfitDealsRate;

Фактически, вот и вся инфраструктура для тестирования стратегий. Сейчас мы можем обрисовать стратегию как функцию, которая воспринимает набор характеристик, который вызывает initRates первой и updateStratRates с результатом каждого закрытия сделки.
Начальные данные могут быть получены, к примеру так:
Сущность системы заключается в использовании 2-ух экспоненциальных скользящих средних. Вход в рынок осуществляется при выполнении последующих критерий: глобальные pairIndex; % номер/номера для денежной пары/пар
глобальные данные; % блоков данных
глобальные dataBlocksNumber; % Количество блоков данных (в нашем примере 16)

Сейчас подробнее о торговой системе, twoEMA, который покажет как все это работает.
Приобрести/реализовать, раз выполнены последующие условия:
1) стремительная скользящая средняя находится выше/ниже медленной не наименее чем определенное количество 4-значных пт;
2) Стоимость открытия таймфрейм выше/ниже стремительной скользящей средней;
3) нет текущих открытых сделок.
Закрытие при одновременном выполнении последующих критерий:
1) при достижении установленного значения прибыли для текущей транзакции;
2) достижение установленного значения утрат для текущей транзакции (tralling стоп-лосс в качестве дохода по сделке он подъезжает к текущей стоимости, пока мы не достигнем безубыточности значения);
3) условия 1 и 2 для открытия сделки в противоположном направлении.
Входные характеристики сделки: длина интервалы в секундах, характеристики скользящих средних в единицах 0.0001, разрыв меж скользящих средних для открытия сделки, величины прибыли и убытков в 4-значных пт.
В демо-режиме, в отличие от отладки, оценки-это не лишь закрытые сделки, но также открыть для оценки наибольшей прибыли на сделку, наибольший убыток по сделке, а также суммарного дохода/убытка на момент закрытия сделки. Не считая того, предусмотрены два режима работы стратегии: отладки и демонстрации.
Таковым образом, любая транзакция может быть представлена эталон «бар» заместо обычного линейного графика Эквити. Прибыль считается в 4 пипсах.
twoEMA.м:
раз dealDir == 1% Раз есть открытая транзакция

% обновлено текущее состояние транзакции
currDeal = bidPrices( currTime + тик ) — openDealPrice;

currEQmin = мин( currDeal, currEQmin );
currEQmax = Макс( currDeal, currEQmax );
currEQclose = currDeal;

% обновлен текущий стоп-лосс
стоп-лосс = Макс( стоп-лосс, bidPrices( currTime + тик ) — Р( 5 ) * 0.0001 );

% проверка на закрытие по стоп-лосс либо тейк-профит
раз либо( bidPrices( currTime + тик ) <= стоп-лосс, … +—————————————————————+
%}

глобальные pairIndex;

глобальные данные;
глобальные dataBlocksNumber;

глобальные WithPlot; % либо демо-режим отладки
глобальный эквалайзер; % баров капитала
глобальные eqCounter; % количество баров

% проверка значений входных характеристик на валидность
раз либо( р( 1 ) < 0, … и( dealDir == 1, сигнал == -1 ), … bidPrices( currTime + тика ) >= тейк профит … на трейлинг-стоп-лосс либо тейк-профит!!! Характеристики:! currTime = currTime + ТФ;

% определения длины интервалы (крайний интервалы могут быть
% короче, чем другие)
barLen = ТФ;
раз T == tfNumb
barLen = dataLen — ТС * ( tfNumb — 1 );
конец

для галочки = 2:(barLen — 1) % всех клещей в сроки… функция к [Z] = twoEma( П )

%{
+—————————————————————+!!! таймфрейм = р(1)!! ) … Е1 — медленной EMA с альфа = р(2)!! либо( р( 2 ) * 0.0001 <= 0, п( 2 ) * 0.0001 >= 1 ), … ) … ) … Е2 — стремительной EMA с альфа = п(3)!!!! либо( р( 3 ) * 0.0001 <= р( 2 ) * 0.0001, р( 3 ) * 0.0001 >= 1 ) … )

initRates( 1 ); % Раз значения входных характеристик является недопустимым, свойства стратегии
% инициализировать очевидно нехороших значений

Для Z = 1;
возврат;

конец

initRates( 0 ); % инициализируем значения характеристик стратегии

% инициализация значений баров текущей сделки
currEQopen = 0;
currEQmin = 0;
currEQmax = 0;
currEQclose = 0;

ТФ = округл( р( 1 ) ); % длина интервалы

для currBlock = 1:dataBlocksNumber

currData = данные{ currBlock };
dataSize = Размер( currData );
dataLen = dataSize( 1 );
tfNumb = натяжн( dataLen / ФТ );

% подготовка массивов bid и ask для текущего блока данных
bidPrices = currData( :, 2 * ( pairIndex — 1) + 1 );
askPrices = currData( :, 2 * pairIndex );

% инициализация рабочих переменных
dealDir = 0;
openDealPrice = 0;
стоплосс = 0;
тейкпрофит = 0;
currDeal = 0;
сигнал = 0;

Е1 = bidPrices( 1 );
Е2 = bidPrices( 1 );

currTime = 1;

для t = 2:tfNumb % на всех таймфреймах… Закрыть:!! недлинные сделки: (openPrice <= Е2 < Е1) и abs(Е1 — Е2) >= Р(4)!!!! )

dealDir = 0;

% обновление стратегии свойства
updateStratRates( currDeal );

% раз демо режим, закрытия бара
% текущей сделки
раз WithPlot
[Эквалайзер, eqCounter] = updateSeries( эквалайзер, eqCounter, [currEQopen, currEQmax, currEQmin, currEQclose] );
конец

конец

конец

раз dealDir == -1%, раз открыта сделка на продажу

currDeal = openDealPrice — askPrices( currTime + тик );

currEQmin = мин( currDeal, currEQmin );
currEQmax = Макс( currDeal, currEQmin );
currEQclose = currDeal;

% обновлен текущий стоп-лосс
стоп-лосс = мин( стоп-лосс, askPrices( currTime + тика ) + Р( 5 ) * 0.0001 );

% проверка на закрытие по стоп-лосс либо тейк-профит
раз либо( askPrices( currTime + тика ) >= стоп-лосс, … либо( стр.( 5 ) * 0.0001 <= 0, … )

dealDir = 0;

% обновление стратегии свойства
updateStratRates( currDeal );

% раз демо режим, закрытия бара
% текущей сделки
раз WithPlot
[Эквалайзер, eqCounter] = updateSeries( эквалайзер, eqCounter, [currEQopen, currEQmax, currEQmin, currEQclose] );
конец

конец

конец

конец

% когда вы открываете новейшую таймфрейме скользящие средние обновлен
Е1 = Е1 + р( 2 ) * 0.0001 * ( bidPrices( currTime ) — Е1 );
Е2 = Е2 + р( 3 ) * 0.0001 * ( bidPrices( currTime ) — Э2 );

% проверка текущего сигнала для открытия сделки
сигнал = 0;
раз и( и( bidPrices( currTime ) >= Е2, Е2 > Е1 ), АБС( Е1 — Е2 ) >= Р( 4 ) * 0.0001 )
сигнал = 1;
конец
раз и( и( bidPrices( currTime ) <= Е2, Е2 < Е1 ), АБС( Е1 — Е2 ) >= Р( 4 ) * 0.0001 )
сигнал = -1;
конец

% закрытия, раз рынок открыт и есть сигнал для открытия
% противоположного
раз либо( … и( dealDir == -1, сигнал == 1 ) … либо( стр.( 4 ) * 0.0001 <= 0, … ) … )

dealDir = 0;

% обновление стратегии свойства
updateStratRates( currDeal );

% раз демо режим, закрытия бара
% текущей сделки
раз WithPlot
[Эквалайзер, eqCounter] = updateSeries( эквалайзер, eqCounter, [currEQopen, currEQmax, currEQmin, currEQclose] );
конец

конец

% открываем сделку на покупку
раз и( dealDir == 0, сигнал == 1 )

dealDir = 1;
openDealPrice = askPrices( currTime ); % открыть прайс

% стоп-лосс и тейк-профит
стоп-лосс = bidPrices( currTime + тик ) — Р( 5 ) * 0.0001;
тейкпрофит = bidPrices( currTime + тика ) + р( 6 ) * 0.0001;

% инициализируем значения Эквити бар
currEQopen = askPrices( currTime + тик ) — bidPrices( currTime + тик );
currEQmin = askPrices( currTime + тик ) — bidPrices( currTime + тик );
currEQmax = askPrices( currTime + тик ) — bidPrices( currTime + тик );
currEQclose = askPrices( currTime + тик ) — bidPrices( currTime + тик );

конец

% открытие на продажу
раз и( dealDir == 0, сигнал == -1 )

dealDir = -1;
openDealPrice = bidPrices( currTime ); % открыть прайс

% стоп-лосс и тейк-профит
стоп-лосс = askPrices( currTime + тика ) + Р( 5 ) * 0.0001;
тейкпрофит = askPrices( currTime + тик ) — р( 6 ) * 0.0001;

% инициализируем значения Эквити бар
currEQopen = askPrices( currTime + тик ) — bidPrices( currTime + тик );
currEQmin = askPrices( currTime + тик ) — bidPrices( currTime + тик );
currEQmax = askPrices( currTime + тик ) — bidPrices( currTime + тик );
currEQclose = askPrices( currTime + тик ) — bidPrices( currTime + тик );

конец

конец

% закрыть все открытые сделки
раз dealDir ~= 0

% обновление стратегии свойства
updateStratRates( currDeal );

% раз демо режим, закрытия бара
% текущей сделки
раз WithPlot
[Эквалайзер, eqCounter] = updateSeries( эквалайзер, eqCounter, [currEQopen, currEQmax, currEQmin, currEQclose] );
конец

конец

конец

По Z = 0;

В приведенном выше листинге употребляет вспомогательную функцию updateSeries, это собственного рода «push_back». Открыть:!! длинноватые сделки: (openPrice >= Е2 > Е1) и abs(Е1 — Е2) >= Р(4)!! либо( стр.( 6 ) * 0.0001 <= 0, … askPrices( currTime + тик ) <= тейк профит … либо( … !
Функция updateSeries.м:
функция [Ю, Я] = updateSeries(ы, я, в)

раз (я == 0

Ы = в;
Я = 1;

еще

Я = Я + 1;
С = [С, В];

конец

И в конце концов, как его можно применять совместно:
Сценарий mainScript.м:
% loadPrices; % загрузка данных

глобальные stratName;
глобальные returnParamIndex;

глобальные pairIndex;
глобальные данные;
глобальных цен;
глобальные dataBlocksNumber;

глобальные WithPlot;
глобальный эквалайзер;
глобальные eqCounter;

stratName = ‘twoEma’; % тест twoEMA

pairIndex = 2; % 2-ой денежной пары (евро/бакс)

ДАННЫЕ = ЦЕН;

dataBlocksNumber = 16;

WithPlot = ересь; % режим отладки

П= [900, 100, 310, 25, 100, 40]; % исходные значения

returnParamIndex = 7; % оптимизации коэффициента Шарпа

Р = fminsearch( ‘testStrat’, Р );
экран(Р);

WithPlot = истина; % демо режим
Экв = 0;
eqCounter = 0;
returnParamIndex = 0;
Р = testStrat( Р );

экран(Р);

для i = 2:eqCounter % управляемый баров на сделки совокупный разум

Эквалайзер( я, 1 ) = экв( я, 1 ) + эквалайзер( я — 1, 4 );
Эквалайзер( я, 2 ) = экв( я, 2 ) + эквалайзер( я — 1, 4 );
Эквалайзер( я, 3 ) = экв( я, 3 ) + эквалайзер( я — 1, 4 );
Эквалайзер( я, 4 ) = экв( я, 4 ) + эквалайзер( я — 1, 4 );

конец

свеча(эквалайзера(:, 2), эквалайзер(:, 3), эквалайзер(:, 4), эквалайзер(:, 1)); Заголовок(‘капитала’);

В итоге, стоимость акций торговой системы будет смотреться последующим образом:

И индивидуальности:
Просадка: 0.0105
Восстановление: 12.6103
Капитал: 0.1320
DealsNumber: 47
MeanDeal: 0.0028
DealsSigma: 0.0056
Диез: 0.5034
ProfitFactor: 3.3393
ProfitDealsNumber: 34
ProfitDealsRate: 0.7234
ProfitMean: 0.0055
LossDealsNumber: 13
LossDealsRate: 0.2766
LossMean: -0.0043
что и не умопомрачительно, как минимум, необходимо применять наиболее интеллектуальные функции поиска оптимума, чем fminsearch, беря во внимание, что у нас нет основания предполагать, что мотивированная функция является гладкой, безпрерывно дифференцируемой и nomodules… Могло бы быть лучше…
И возможность с помощью MATLAB демонстрируются. Но у нас не было цели сделать супер систему. habrahabr.ru