![]() |
Здравствуйте, гость ( Вход | Регистрация )
![]() ![]() |
![]() |
leonid553 |
![]()
Сообщение
#1
|
![]() Группа: Активный участник Сообщений: 2 002 Регистрация: 14.4.2006 Из: г.Самара Пользователь №: 28 Спасибо сказали: 11 раз(а) ![]() |
Yury V. Reshetov
Нейронная сеть Что такое нейронная сеть или Perceptron? Это алгоритм использующий уравнение линейного неравенства (линейного фильтра), с помощью которого можно причислить исследуемый объект к тому или иному классу или же наоборот исключить его из этого самого класса объектов. Само неравенство выглядит так: w1 * a1 + w2 * a2 + ... wn * an > d где: 1. wi - весовой коэффициент с индексом i; 2. ai - численное значение признака с индексом i исследуемого объекта; 3. d - пороговое значение, чаще всего равное 0. Дело в том, что геометрически плоскость описывается линейным уравнением. Например, в трехмерном пространстве относительно координат X, Y и Z уравнение плоскости имеет вид: A * X + B * Y + C * Z + D = 0 Координаты всех точек, расположенных по одну сторону от плоскости, в этом самом пространстве, удовлетворяют неравенству: A * X + B * Y + C * Z + D > 0 А координаты всех точек лежащих по другую сторону от плоскости, удовлетворяют неравенству: A * X + B * Y + C * Z + D < 0 Таким образом, если нам известно уравнение некой плоскости и координаты любых точек, то мы можем разделить множество всех точек пространства на два множества точек, разделяемых этой самой плоскостью. ПОСТАНОВКА ЗАДАЧИ Если мы разделим объекты на два класса: открываемые длинные позиции и короткие позиции, а в качестве признаков возьмем значения индикаторов или осцилляторов технического анализа, то остается лишь выяснить уравнение плоскости и попытаться с ее помощью произвести идентификацию. Постановка задачи ясна. Множества точек пересекаются в пространстве и провести четкую разделительную черту между ними невозможно. Единственным и приемлемым решением здесь является линия, которая будет отделять оба множества точек таким образом, чтобы с ее помощью большинство красных объектов оказалось по одну сторону, а синих по другую. На сей раз, мы имеем дело с задачей оптимизации, то есть поиском уравнения разделяющей плоскости или линии, способной максимально разделить два класса объектов друг от друга, но с вероятностью того, что часть точек, принадлежащих одному классу, будет ошибочно идентифицировано, как принадлежащих к классу другому. Попробуем теперь определиться с постановкой задачи, которую мы собираемся решить. Элементарно, что нужно знать трейдеру для прибыльной торговли - это направление движения котировок. То есть если котировки пойдут вверх, то следует открыть длинную позицию. Если вниз, то необходимо открывать позицию короткую. Следовательно, два класса объектов у нас уже есть, а именно, направление движения котировок. Для того, чтобы принять решение, следуя техническому анализу, трейдеры прибегают к исследованию так называемых технических индикаторов или осцилляторов. Мы также будем исследовать осциллятор. Поскольку технические осцилляторы - это гистограммы, значения которых отклоняются от горизонтальной линии, то соответственно и нейронная сеть нам понадобится с линейным фильтром. В качестве признаков объекта, будем брать паттерны, то есть значения осциллятора в четырех точках, взятые с шагом в семь периодов вглубь истории, начиная от текущего момента. Эскизы прикрепленных изображений |
leonid553 |
![]()
Сообщение
#2
|
![]() Группа: Активный участник Сообщений: 2 002 Регистрация: 14.4.2006 Из: г.Самара Пользователь №: 28 Спасибо сказали: 11 раз(а) ![]() |
На вышеприведенном рисунке значения осциллятора обведены кружочками. Присвоим их идентификаторам a1, a2, a3 и a4 и будем подставлять в уравнение разделительной плоскости и сравнивать полученное значение с нулем, чтобы узнать, с какой стороны будет находиться паттерн. Осталось только получить само уравнение плоскости, которое будет разделять паттерны, предшествующие движению цены вверх, от паттернов, предшествующих движению цены вниз. Для этой цели будем использовать встроенный в торговый терминал MetaTrader4 генетический алгоритм, предназначенный для ускорения процессов оптимизации. Проще говоря, мы будем подбирать значения весовых коэффициентов линейного фильтра таким образом, чтобы в результате получить уравнение разделительной линии для максимального значения баланса оптимизацией стратегии на исторических данных. Для этой цели нам понадобится, как минимум, формулировка торговой стратегии, с помощью которой можно будет реализовать алгоритм и переложить его в код советника для MetaTrader4. Теоретически торговая система должна предусматривать сигналы, как для входа в рынок, так и для выхода из него. Впрочем, выходы по сигналам не являются обязательными и их можно исключить с помощью: Расстановки стоп-ордеров - takeprofit и stoploss; Разворотом позиции в противоположном направлении при получении сигнала о изменении направления тенденции рынка. Чтобы не усложнять торговую систему, мы будем использовать выходы по защитным стопам - stoploss и по сигналам разворотов. В этом случае нейросеть будет выдавать на выходе только два сигнала по значениям признаков объектов, а именно: Котировки вероятнее всего будут двигаться в сторону повышения; Котировки вероятнее всего будут двигаться в сторону понижения. Таким образом упрощается задача идентификации объектов для нейронной сети путем разделения их всего на два класса. Оптимизацию торговой системы также можно упростить, исключив из управления ордерами фиксацию прибылей по takeprofit, то есть избавить ее от подбора еще одного входного параметра. В этом случае достаточно воспользоваться трейлинг-стопами, то есть постепенными подтягиваниями stoploss в прибыльную сторону до тех пор, пока нейросеть не даст противоположный сигнал или пока она не ошибется. Любая ошибка нейросети приведет к срабатыванию защитного стопа. При этом сама система управления ордерами усложняется. Быстрый разворот позиции в обратном направлении лучше всего выполнить через встречный ордер с удвоенным количеством лотов и последующим закрытием встречной позиции. Этот маневр позволяет совершить все операции по развороту сразу же, как только будет получен сигнал от нейросети. Чтобы сократить количество ложных срабатываний от сигналов нейросети, их считывание и принятие решений будем производить только по сформировавшимся барам и по ценам открытия этих самых баров. Решение задачи Ниже приведен исходный код советника, реализующего данную торговую стратегию: //+------------------------------------------------------------------+ //| ArtificialIntelligence.mq4 | //| Copyright й 2006, Yury V. Reshetov | //| http://reshetov.xnet.uz/ | //+------------------------------------------------------------------+ #property copyright "Copyright й 2006, Yury V. Reshetov ICQ:282715499 http://reshetov.xnet.uz/" #property link "http://reshetov.xnet.uz/" //---- input parameters extern int x1 = 120; extern int x2 = 172; extern int x3 = 39; extern int x4 = 172; // StopLoss level extern double sl = 50; extern double lots = 0.1; extern int MagicNumber = 888; static int prevtime = 0; static int spread = 3; //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { //---- return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- return(0); } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() { if(Time[0] == prevtime) return(0); prevtime = Time[0]; //---- if(IsTradeAllowed()) { spread = MarketInfo(Symbol(), MODE_SPREAD); } else { prevtime = Time[1]; return(0); } int ticket = -1; // check for opened position int total = OrdersTotal(); for(int i = 0; i < total; i++) { OrderSelect(i, SELECT_BY_POS, MODE_TRADES); // check for symbol & magic number if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber) { int prevticket = OrderTicket(); // long position is opened if(OrderType() == OP_BUY) { // check profit if(Bid > (OrderStopLoss() + (sl * 2 + spread) * Point)) { if(perceptron() < 0) { // reverse ticket = OrderSend(Symbol(), OP_SELL, lots * 2, Bid, 3, Ask + sl * Point, 0, "AI", MagicNumber, 0, Red); Sleep(30000); if(ticket < 0) { prevtime = Time[1]; } else { OrderCloseBy(ticket, prevticket, Blue); } } else { // trailing stop if(!OrderModify(OrderTicket(), OrderOpenPrice(), Bid - sl * Point, 0, 0, Blue)) { Sleep(30000); prevtime = Time[1]; } } } // short position is opened } else { // check profit if(Ask < (OrderStopLoss() - (sl * 2 + spread) * Point)) { if(perceptron() > 0) { // reverse ticket = OrderSend(Symbol(), OP_BUY, lots * 2, Ask, 3, Bid - sl * Point, 0, "AI", MagicNumber, 0, Blue); Sleep(30000); if(ticket < 0) { prevtime = Time[1]; } else { OrderCloseBy(ticket, prevticket, Blue); } } else { // trailing stop if(!OrderModify(OrderTicket(), OrderOpenPrice(), Ask + sl * Point, 0, 0, Blue)) { Sleep(30000); prevtime = Time[1]; } } } } // exit return(0); } } // check for long or short position possibility if(perceptron() > 0) { //long ticket = OrderSend(Symbol(), OP_BUY, lots, Ask, 3, Bid - sl * Point, 0, "AI", MagicNumber, 0, Blue); if(ticket < 0) { Sleep(30000); prevtime = Time[1]; } } else { // short ticket = OrderSend(Symbol(), OP_SELL, lots, Bid, 3, Ask + sl * Point, 0, "AI", MagicNumber, 0, Red); if(ticket < 0) { Sleep(30000); prevtime = Time[1]; } } //--- exit return(0); } //+------------------------------------------------------------------+ //| The PERCEPRRON - a perceiving and recognizing function | //+------------------------------------------------------------------+ double perceptron() { double w1 = x1 - 100.0; double w2 = x2 - 100.0; double w3 = x3 - 100.0; double w4 = x4 - 100.0; double a1 = iAC(Symbol(), 0, 0); double a2 = iAC(Symbol(), 0, 7); double a3 = iAC(Symbol(), 0, 14); double a4 = iAC(Symbol(), 0, 21); return (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4); } //+------------------------------------------------------------------+} Осталось только подобрать весовые коэффициенты линейного уравнения разделительной плоскости для нейросети. klot писал: Спасибо! Всё досупно и правильно написано. Я тут немного модернизировал Вашего советника, - попробовал сделать "многослойную сеть" из 4-х перцептронов.У каждого свой состав входов и каждый обучался отдельно на максимальную прибыль. Потом, 5-й обобщал результаты (обучался на минимизацию просадки) предыдущих 4-х. Получилось не плохо, много сделок и просадка не большая. А вообще, мне нравиться, эту тему я давно изучаю. Правда зашел через "парадный вход" начал с самых истоков. Если есть желание посотрудничать обсуждение идёт тут: http://www.fxexpert.ru/forum/index.php?showtopic=656 Yury V. Reshetov Я тоже попробовал 5-ти слойку. Первые 4 имеют по 5 входов, на каждый из которого поступают нормированные значения с отдельно взятого индикатора (на каждый слой свой индикатор). 5-й слой 4-х входовый и также обобщающий. Результаты весьма неплохие получаются. Самое главное, что вне репрезентативной выборки ведет себя очень стабильно по сравнению с однослойкой. Удобно тем, что каждый слой можно обучать по отдельности. Осталось только полностью автоматизировать весь процесс обучения на истории. Лучший вариант - это взять сразу 4 компьютера и распараллелить процессы обучения. Потом собрать результаты с 4 слоев воедино и обучить последний слой. |
leonid553 |
![]()
Сообщение
#3
|
![]() Группа: Активный участник Сообщений: 2 002 Регистрация: 14.4.2006 Из: г.Самара Пользователь №: 28 Спасибо сказали: 11 раз(а) ![]() |
GBPJPY, H1
Тест за янв-февр-март после оптимизации за ноябрь-дек. 2006г(по ценам откр.): Баров в истории 2348 Начальный депозит 1000.00 Чистая прибыль 3911.07 Общая прибыль 5859.70 Общий убыток -1948.63 Прибыльность 3.01 Матожидание выигрыша 35.23 Абсолютная просадка 50.84 Максимальная просадка 177.91 (1.49%) Относительная просадка 1.49% (177.91) Всего сделок 111 Короткие позиции (% выигравших) 46 (63.04%) Длинные позиции (% выигравших) 65 (61.54%) Прибыльные сделки (% от всех) 69 (62.16%) Убыточные сделки (% от всех) 42 (37.84%) Самая большая прибыльная сделка 514.66 убыточная сделка -55.72 Средняя прибыльная сделка 84.92 убыточная сделка -46.40 Максимальное количество непрерывных выигрышей (прибыль) 7 (349.35) непрерывных проигрышей (убыток) 3 (-150.10) Максимальная непрерывная прибыль (число выигрышей) 632.37 (2) непрерывный убыток (число проигрышей) -150.10 (3) Средний непрерывный выигрыш 2 непрерывный проигрыш 1 Эскизы прикрепленных изображений |
leonid553 |
![]()
Сообщение
#4
|
![]() Группа: Активный участник Сообщений: 2 002 Регистрация: 14.4.2006 Из: г.Самара Пользователь №: 28 Спасибо сказали: 11 раз(а) ![]() |
to NoName:
Твоя последняя версия "ST+ENV" - с переворотом, работает оч. прилично! Сам не ожидал! Выгребает тренд - почти до дна! Появилась мысль вставить в советник перцептрон с вызовом другого индикатора! Чтобы уменьшить число убыточных, нетрендовых входов. |
NoName |
![]()
Сообщение
#5
|
![]() Группа: Активный участник Сообщений: 514 Регистрация: 1.5.2006 Из: Украина, Кременчуг Пользователь №: 146 Спасибо сказали: 0 раз(а) ![]() |
Цитата to NoName: Твоя последняя версия "ST+ENV" - с переворотом, работает оч. прилично! Сам не ожидал! Выгребает тренд - почти до дна! Появилась мысль вставить в советник перцептрон с вызовом другого индикатора! Чтобы уменьшить число убыточных, нетрендовых входов. А я так и не смог от неё ничего путнего получить. Как не крутил - на бэктесте всё сливает, зараза. Так что подгонка, как говорится, на лицо ![]() На счёт перцептрона, а почему бы в сеть не подать сигналы самих "ST+ENV", без вызовов всяких индикаторов? Я примерно представляю как это программно описать, нужно будет индикатор состряпать. Но этим если и заниматься, то нужно создавать нормальную нейросеть, а то этот советник уж больно примитивный ![]() P.S. Наверное неплохо бы ветку отдельную сделать для этого. И сообщения последние туда перенести. А то ты немного не туда забрёл ![]() ![]() |
leonid553 |
![]()
Сообщение
#6
|
![]() Группа: Активный участник Сообщений: 2 002 Регистрация: 14.4.2006 Из: г.Самара Пользователь №: 28 Спасибо сказали: 11 раз(а) ![]() |
"А я так и не смог от неё ничего путнего получить. Как не крутил - на бэктесте всё сливает, зараза. Так что подгонка, как говорится, на лицо "
--------------------------------------------------------------------------- Я тоже изначально не мог получить удовлетворительных результатов. Но потом дошло, в чем тут дело!! Посмотрел в визуале работу нейро советника и обнаружил - как грамотно он работает при трендовом рынке. По аналогии предусмотрел аналогичную комбинацию внешних параметров в ST+ENV, отказался от тейкпрофита (ну почти, сделал его = 250/300). Заменил его тралом, оптимизировал шаг трала - Tr/Step . При этом обнаружилось, что теперь и наш советник "выгребает тренд" оч. неплохо! Имеются, конечно "отдельные недостатки" - о них я писал в НЕСТАНДАРТНОЙ ТАКТИКЕ. ----------------------------------------------------------------------------------- "На счёт перцептрона, а почему бы в сеть не подать сигналы самих "ST+ENV", без вызовов всяких индикаторов? Я примерно представляю как это программно описать, нужно будет индикатор состряпать. Но этим если и заниматься, то нужно создавать нормальную нейросеть, а то этот советник уж больно примитивный " ----------------------------------------------------------------------------------- Поскольку индикатор ты уже "состряпал", то я вижу примерно такой сценарий: Решетов писал: "Я тоже попробовал 5-ти слойку. Первые 4 имеют по 5 входов, на каждый из которого поступают нормированные значения с отдельно взятого индикатора (на каждый слой свой индикатор). 5-й слой 4-х входовый и также обобщающий. Результаты весьма неплохие получаются. Самое главное, что вне репрезентативной выборки ведет себя очень стабильно по сравнению с однослойкой." Поэтому наш ST+ENV будет давать только сигналы на вход и сопровождать позицию, как "базовый" узел. А достоверность его сигналов будет проверяться (для начала) однослойной нейро структурой с др. индикатором. Причем работу однослойки желательно постоить на меньшем тф, чем тот на кот. работает ST+ENV!. Чтобы "не задерживаться со входом. А на счет того - как программно подать в сеть сигналы самого ST+ENV, - увы... Не могу пока сообразить. ![]() |
NoName |
![]()
Сообщение
#7
|
![]() Группа: Активный участник Сообщений: 514 Регистрация: 1.5.2006 Из: Украина, Кременчуг Пользователь №: 146 Спасибо сказали: 0 раз(а) ![]() |
Цитата Поскольку индикатор ты уже "состряпал", то я вижу примерно такой сценарий: Решетов писал: "Я тоже попробовал 5-ти слойку. Первые 4 имеют по 5 входов, на каждый из которого поступают нормированные значения с отдельно взятого индикатора (на каждый слой свой индикатор). 5-й слой 4-х входовый и также обобщающий. Результаты весьма неплохие получаются. Самое главное, что вне репрезентативной выборки ведет себя очень стабильно по сравнению с однослойкой." Поэтому наш ST+ENV будет давать только сигналы на вход и сопровождать позицию, как "базовый" узел. А достоверность его сигналов будет проверяться (для начала) однослойной нейро структурой с др. индикатором. Причем работу однослойки желательно постоить на меньшем тф, чем тот на кот. работает ST+ENV!. Чтобы "не задерживаться со входом. А на счет того - как программно подать в сеть сигналы самого ST+ENV, - увы... Не могу пока сообразить. sad.gif То что я состряпал - это не для сети делалось. На счёт подачи сигналов (не только ST+Env) думаю уже не один день. Пока вижу это так: представь что в момент возникновения сигнала, когда мы совершаем сделку, на график наносится стрелочка в этом месте. Получится два вида стрелочек, вверх (при покупке) и вниз (при продаже). Мы будем иметь график, на котором будут проставлены стрелочки по всей истории (заданной). Далее нужно выгрузить в файл весь ценовой ряд, которому необходимо поставить в соответствие наши сигналы. Там где стрелка вверх мы будем ставить 1, там где вниз поставим (-1), а там где стрелочек нет - 0. И вот в таком виде эти данные нужно скормить Нейрошелу. Меня останавливает вот что. Тактика ST+ENV подразумевает работу внутри бара. Если мы будем подавать сигналы по закрытию бара, то будет упускаться значительная часть движения (или же сигнала не окажется вовсе, т.к. не редко бывает что вход и выход получаются в пределах одного бара при сильных движениях). Ну а подавать в нейросеть минутки - мне кажется что это глупость. Возможно, что хорошим выходом из этой ситуации будет использования меньшего ТФ, то есть вместо минуток подавать М5 или М15, но смотреть при этом на Н4. Скорее всего к оптимальному результату можно прийти только методом проб и ошибок. |
leonid553 |
![]()
Сообщение
#8
|
![]() Группа: Активный участник Сообщений: 2 002 Регистрация: 14.4.2006 Из: г.Самара Пользователь №: 28 Спасибо сказали: 11 раз(а) ![]() |
Вот такая ещё идея .
ПО вышеприведенному советнику. Там перцептрон обрабатывает значения индикатора AO, взятые из четырех точек. И потом выдает суммарный итог - "+" или "-". Если нам ввести дополнително еще: ----------------------------------------------------------------- double perceptron_2() { double w1 = x1 - 100.0; double w2 = x2 - 100.0; double w3 = x3 - 100.0; double w4 = x4 - 100.0; double a1 = iRVI(Symbol(), 0, RVI_period,MODE_MAIN,0); double a2 = iRVI(Symbol(), 0, RVI_period,MODE_MAIN,7); double a3 = iRVI(Symbol(), 0, RVI_period,MODE_MAIN,14); double a4 = iRVI(Symbol(), 0, RVI_period,MODE_MAIN,21); return (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4); } -------------------------------------------------------------------------- а потом еще: ----------------------------------------------------------------------- double perceptron_3() { double w1 = x1 - 100.0; double w2 = x2 - 100.0; double w3 = x3 - 100.0; double w4 = x4 - 100.0; double a1 = iCCI(Symbol(), 0,CCI_period, PRICE_CLOSE, P_1); double a2 = iCCI(Symbol(), 0,CCI_period, PRICE_CLOSE, P_2); double a3 = iCCI(Symbol(), 0, CCI_period, PRICE_CLOSE, P_3); double a4 = iCCI(Symbol(), 0,CCI_period, PRICE_CLOSE, P_4); return (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4); } ---------------------------------------------------------------------------- и наконец ещё: double perceptron_4() .... ..... .... double a1 = iStochastic(Symbol ..... ..... ----------------------------------------------------------------------------- А ДАЛЕЕ заявить последний - суммирующий : double perceptron_SUM, на входы которого и подать значения предыдущих выходов? Непонятно только как организовать: double a1 = iРerceptron_1(...... double a1 = iРerceptron_2(...... и т.д. А в код самого советника вставить именно - полученное значение последнего, суммирующего перцептрона! |
NoName |
![]()
Сообщение
#9
|
![]() Группа: Активный участник Сообщений: 514 Регистрация: 1.5.2006 Из: Украина, Кременчуг Пользователь №: 146 Спасибо сказали: 0 раз(а) ![]() |
Я ведь тебе предлагал уже это по аське! Можно вообще все индикаторы туда засунуть. Можно, также, брать не просто значения с определенных баров, а например, изменение на последнем и предпоследнем баре (например, Close[1]-Close[0]) - тоже может получиться интересный результат.
В любом случае при использовании нескольких перцептронов нужно учитывать "размерность" индикаторов. Т.к. у одних область определения от 0 до 100, у других от 0 до 1, у третих -100 - +100 и т.д. Нужно все показания приводить к одному виду, иначе, последний результирующий перецептрон будет считать показания индикатора с маленькими числами "незначительными". А реализовываться это будет примерно так: Код double perceptron_SUM () { double w1 = x1 - 100.0; double w2 = x2 - 100.0; double w3 = x3 - 100.0; double w4 = x4 - 100.0; double a1 = perceptron_1 (); double a2 = perceptron_2 (); double a3 = perceptron_3 (); double a4 = perceptron_4 (); return (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4); } Вот только переменные весовых коэффициентов для разных прецептронов, наверное, должны быть разными. |
leonid553 |
![]()
Сообщение
#10
|
![]() Группа: Активный участник Сообщений: 2 002 Регистрация: 14.4.2006 Из: г.Самара Пользователь №: 28 Спасибо сказали: 11 раз(а) ![]() |
Либо подбирать индикаторы , средняя линия которых равна нулю!
|
![]() ![]() |
![]() |
Текстовая версия | Сейчас: 6.9.2024, 20:20 |