Решил побахвалиться. Еще одна разновидность нейросетки. - страница 4

 
Debugger:

Нет это не мое изобретение. Просто из нашего разговора я понимаю что уровень Вашего образования в этом направлении ниже плинтуса (без обид) :))
Заходите к нам ещё.
 
И Вас чмоки.... :))
 
Debugger:


Уверен автор этого поста (Reshetov) не обладает столь обширными знаниями и навыками, чтобы написать то о чем он заявил, иначе бы он не писал бы это...

Надеюсь понятно изъясняюсь... :))


Ну, конечно же не обладаю! Всё это - плод моей бурной фантазии и буйной графомании.

Даже не надейтесь, изъясняетесь Вы более чем понятно.

 

Допилил R-Net. Теперь дополнительным условием остановки кластеризации является отсутствие противоречий в данном кластере. Т.е. если все обучающие примеры текущего кластера - система линейных уравнений, решением которой являются веса перцептрона, то противоречий больше нет и дальнейшая кластеризация бессмысленна.

Вот что получилось.

Идентифицируем птицу:

double getResult(double x1, double x2, double x3, double x4, double x5, double x6) {
  double result = 0d;
  result = 0.500082 * x3 + 0.499918 * x5;
  return (result);
}

Получили правильный ответ сразу без всякой кластеризации по наличию клюва - x3 и оперения - x5, которые однозначно и отличают птицу от всех остальных объектов в обучающей выборке. До этого R-Net для идентификации той же самой птицы проводил двойную кластеризацию.

Идентифицируем муху:

double getResult(double x1, double x2, double x3, double x4, double x5, double x6) {
  double result = 0d;
  result =  -1.0 * x2;
  return (result);
}

Опять получили правильный ответ без кластеризации, т.к. муха однозначно отличается от всех остальных объектов отсутствие хвоста - переменная x2. Ранее для получения правильного ответа приходилось применять одну кластеризацию.

Идентифицируем самолет:

double getResult(double x1, double x2, double x3, double x4, double x5, double x6) {
  double result = 0d;
  if (x3 > 0d) {
    result = -1.0;
  } else {
    result = 0.49866448983511696 * x3 + 1.0000780298073864 * x4 + 0.5018276981807049 * x5 + 1.0005702178232083 * x6;
  }
  return (result);
}

Практически ничего не изменилось по сравнению с идентификацией до усовершенствования R-Net, т.е. самолет можно точно идентифицировать, применив как минимум 1 этап кластеризации, т.е. однослойным перцептроном он не аппроксимируется.

Идентифицируем планер:

double getResult(double x1, double x2, double x3, double x4, double x5, double x6) {
  double result = 0d;
  result =  -1.0008434841599076 * x1 - 1.0008584927748525 * x4 + 1.0000150086149449 * x6;
  return (result);
}

Кластеризация на сей раз не понадобилась. Аппроксимация обычным перцептроном прошла успешно.

Идентифицируем ракету:

double getResult(double x1, double x2, double x3, double x4, double x5, double x6) {
  double result = 0d;
  result =  -1.0 * x1;
  return (result);
}

Здесь все также как и прежде, без кластеризации.

Попробуем распознать биологические объекты, по признакам, отличающих их от механических:

double getResult(double x1, double x2, double x3, double x4, double x5, double x6) {
  double result = 0d;
  if (x5 > 0d) {
    result = 1.0;
  } else {
    result =  -1.0 * x2;
  }
  return (result);
}

Кластеризация в один этап. Ранее применялась двойная кластеризация.

Итак удалось довести R-Net до совершенства обучающей выборке с отсутствием противоречий.

Дальнейшие испытания на столь примитивных примерах можно завершить, т.к. здесь достигнут полный успех.


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

 

Начнем с простой постановки задачи, а именно есть ли возможность пройти отбор советников на исторических данных? Т.е. если ТС не в состоянии сколь нибудь показать результаты даже на подгонке под историю, то этот этап не будет пройден и подавать заявку на участие нет никакого смысла.

ТС будет примитивной. А именно по сформировавшемуся бару на D1 она попытается полученной R-Net нейросетью вычислить следующее направление движения котировок до формирования следующего бара и открыть позицию в этом самом направлении.

Для тестирования возможностей R-Net возьмем прогнозирование прироста цены в % между от момента формирования текущего бара и до начала формирования следующего, т.е. на 1 бар по ценам открытия. В качестве входов будем подавать значения предыдущих приростов цены в % за разные периоды, т.е. от 1 до 62 баров. Итого получаем нейросеть с 62 входами. Испытательным полигоном будет EURUSD. Поскольку время существования Euro не столь велико - всего несколько тысяч дневных баров, то можно попытаться построить математическую модель всей доступной истории EURUSD.

Т.к. MQL5 я еще недостаточно изучил, то для выкачивания необходимой информации будет использоваться советник на MQL4.

 

Вот и код советника, который выкачивает из истории информацию для нашей задачи и выгружает ее в формате *.csv

Файлы:
r-net_1.mq4  5 kb
 
А вот и сам r-net.csv, упакованный ZIP-ом
Файлы:
r-net.zip  918 kb
 

Скормили нашу информацию R-Net и получили исходники математической модели - базы знаний дневных доходностей EURUSD в % за всю историю его существования. Всего 1113 строчек на C подобном языке.

Возможно, что котировки были битые или дырявые? Я не проверял. Для чемпионата можно будет достать данные из более достоверных источников. Сейчас не это важно, т.к. судя по разветвленности условных операторов, предсказуемость должна быть низкой, объемы противоречивых данных велики. Теперь нужно проверить расхождения между между данными выкачанными из истории и вычисленными по математической модели.

Файлы:
 

Делаем вот такую проверялку на Java:

package test;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;

/**
 * <p>Title: Test</p>
 * <p>Description: Test</p>
 * <p>Copyright: Copyright (c) 2010</p>
 * <p>Company: Reshetov & Co</p>
 * @author Yury V. Reshetov
 * @version 1.0
 */

public class Frame1 extends Frame {
  TextArea ta = new TextArea();
  Panel panel1 = new Panel();
  Panel panel2 = new Panel();
  Panel panel3 = new Panel();
  Panel panel4 = new Panel();
  Button button1 = new Button();

  public Frame1() {
    try {
      jbInit();
      this.pack();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }
  private void jbInit() throws Exception {
    button1.setLabel("Start");
    button1.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        button1_actionPerformed(e);
      }
    });
    this.addWindowListener(new java.awt.event.WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        this_windowClosing(e);
      }
    });
    this.add(ta, BorderLayout.CENTER);
    this.add(panel1, BorderLayout.SOUTH);
    panel1.add(button1, null);
    this.add(panel2, BorderLayout.WEST);
    this.add(panel3, BorderLayout.EAST);
    this.add(panel4, BorderLayout.NORTH);
  }

  void button1_actionPerformed(ActionEvent e) {
    button1.setEnabled(false);
    try {
      FileDialog fd = new FileDialog(this, "Load file for testing", FileDialog.LOAD);
      fd.setFile("*.csv");
      fd.show();
      if (fd.getFile() != null) {
        ta.setText("");
        BufferedReader br = new BufferedReader(new FileReader(fd.getDirectory() + fd.getFile()));
        PrintWriter pw = new PrintWriter(new FileWriter(fd.getDirectory() + "test.txt"));
        String s = "";
        while ((s = br.readLine()) != null) {
          if (! s.equals("")) {
            StringTokenizer st = new StringTokenizer(s, " ;");
            double x0 = Double.parseDouble(st.nextToken().trim());
            double x1 = Double.parseDouble(st.nextToken().trim());
            double x2 = Double.parseDouble(st.nextToken().trim());
            double x3 = Double.parseDouble(st.nextToken().trim());
            double x4 = Double.parseDouble(st.nextToken().trim());
            double x5 = Double.parseDouble(st.nextToken().trim());
            double x6 = Double.parseDouble(st.nextToken().trim());
            double x7 = Double.parseDouble(st.nextToken().trim());
            double x8 = Double.parseDouble(st.nextToken().trim());
            double x9 = Double.parseDouble(st.nextToken().trim());
            double x10 = Double.parseDouble(st.nextToken().trim());
            double x11 = Double.parseDouble(st.nextToken().trim());
            double x12 = Double.parseDouble(st.nextToken().trim());
            double x13 = Double.parseDouble(st.nextToken().trim());
            double x14 = Double.parseDouble(st.nextToken().trim());
            double x15 = Double.parseDouble(st.nextToken().trim());
            double x16 = Double.parseDouble(st.nextToken().trim());
            double x17 = Double.parseDouble(st.nextToken().trim());
            double x18 = Double.parseDouble(st.nextToken().trim());
            double x19 = Double.parseDouble(st.nextToken().trim());
            double x20 = Double.parseDouble(st.nextToken().trim());
            double x21 = Double.parseDouble(st.nextToken().trim());
            double x22 = Double.parseDouble(st.nextToken().trim());
            double x23 = Double.parseDouble(st.nextToken().trim());
            double x24 = Double.parseDouble(st.nextToken().trim());
            double x25 = Double.parseDouble(st.nextToken().trim());
            double x26 = Double.parseDouble(st.nextToken().trim());
            double x27 = Double.parseDouble(st.nextToken().trim());
            double x28 = Double.parseDouble(st.nextToken().trim());
            double x29 = Double.parseDouble(st.nextToken().trim());
            double x30 = Double.parseDouble(st.nextToken().trim());
            double x31 = Double.parseDouble(st.nextToken().trim());
            double x32 = Double.parseDouble(st.nextToken().trim());
            double x33 = Double.parseDouble(st.nextToken().trim());
            double x34 = Double.parseDouble(st.nextToken().trim());
            double x35 = Double.parseDouble(st.nextToken().trim());
            double x36 = Double.parseDouble(st.nextToken().trim());
            double x37 = Double.parseDouble(st.nextToken().trim());
            double x38 = Double.parseDouble(st.nextToken().trim());
            double x39 = Double.parseDouble(st.nextToken().trim());
            double x40 = Double.parseDouble(st.nextToken().trim());
            double x41 = Double.parseDouble(st.nextToken().trim());
            double x42 = Double.parseDouble(st.nextToken().trim());
            double x43 = Double.parseDouble(st.nextToken().trim());
            double x44 = Double.parseDouble(st.nextToken().trim());
            double x45 = Double.parseDouble(st.nextToken().trim());
            double x46 = Double.parseDouble(st.nextToken().trim());
            double x47 = Double.parseDouble(st.nextToken().trim());
            double x48 = Double.parseDouble(st.nextToken().trim());
            double x49 = Double.parseDouble(st.nextToken().trim());
            double x50 = Double.parseDouble(st.nextToken().trim());
            double x51 = Double.parseDouble(st.nextToken().trim());
            double x52 = Double.parseDouble(st.nextToken().trim());
            double x53 = Double.parseDouble(st.nextToken().trim());
            double x54 = Double.parseDouble(st.nextToken().trim());
            double x55 = Double.parseDouble(st.nextToken().trim());
            double x56 = Double.parseDouble(st.nextToken().trim());
            double x57 = Double.parseDouble(st.nextToken().trim());
            double x58 = Double.parseDouble(st.nextToken().trim());
            double x59 = Double.parseDouble(st.nextToken().trim());
            double x60 = Double.parseDouble(st.nextToken().trim());
            double x61 = Double.parseDouble(st.nextToken().trim());
            double x62 = Double.parseDouble(st.nextToken().trim());
            double check = this.getResult(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, 
x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, 
x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61, x62);
            String str = "";
            if ((x0 * check) < 0d) {
              str = " *****";
            }
            pw.println(x0 + ", " + check + ", " + Math.abs(x0 - check) + str);
          }
        }
        pw.flush();
        pw.close();
        br.close();
      }
    } catch (Exception ex) {
      ex.printStackTrace();
    }
    button1.setEnabled(true);
  }

Ниже добавляем функцию математической модели.



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

Первая столбец - реальные данные полученные из исторических.

Второй - вычисленные по математической модели.

Третий - абсолютная разница между реальными данными и вычисленными. Если строчка помечена пятью звездочками, то знак не совпал - линейно несепарабельно.

...
-0.92973477, -1.438481703697436, 0.508746933697436
-0.20199231, -2.6339616502953027, 2.4319693402953027
0.66265369, -9.063431014726032E-7, 0.6626545963431014 *****
-0.64168714, -2.141542441704782, 1.4998553017047818
0.61492341, 0.7076315366068044, 0.0927081266068045
0.16111905, -8.791475050136993E-7, 0.16111992914750503 *****
0.3926153, -7.660625258287673E-7, 0.3926160660625258 *****
-0.1893314, -8.218205955821916E-7, 0.18933057817940444
-0.10336486, -9.293629526095896E-7, 0.1033639306370474
0.45510781, 0.5761408124900687, 0.12103300249006865
-0.84121977, -1.43837043906533, 0.59715066906533
0.62974421, -5.150045159417808E-7, 0.629744725004516 *****
0.30218829, -4.237038464142872E-6, 0.30219252703846416 *****
-0.40081337, -3.4467829215871033, 3.0459695515871035
0.61897551, -4.1830226656904885E-6, 0.6189796930226656 *****
0.0088644, -4.35969895419049E-6, 0.00886875969895419 *****
0.17389631, -2.6853018515714406E-6, 0.17389899530185157 *****
-0.63455416, -2.844057087404771E-6, 0.6345513159429126
-0.09623013, -4.735627050880969E-6, 0.09622539437294912
0.88933685, -5.595961926095254E-6, 0.889342445961926 *****
-0.78091681, -4.775607525404777E-6, 0.7809120343924746
-1.1549392, -1.2775802214975025, 0.12264102149750244
1.18777948, -4.669289923285731E-6, 1.1877841492899235 *****
-0.13881034, -6.681563656119071E-6, 0.13880365843634387
-0.53183329, -6.373379767476209E-6, 0.5318269166202325
-0.32984316, -7.324752849095263E-6, 0.32983583524715093
-0.43714342, -6.612093628428592E-6, 0.43713680790637155
1.01571539, -5.900551350880974E-6, 1.0157212905513509 *****
-0.00366142, -5.453962754857159E-6, 0.003655966037245143
-0.52013142, -6.352165685904783E-6, 0.5201250678343141
-1.17063478, -7.879712499785739E-6, 1.1706269002875003
-0.56055898, -6.575088934904786E-6, 0.5605524049110652
...

Как и ожидалось, чуда не произошло. Разница между реальными и вычисленными данными достаточно высокая. В некоторых случаях даже знак распознать не удалось. В общем, так и должно быть, ведь R-Net не пытается подогнать желаемое под действительное, а делает это только в тех случаях, когда отсутствуют противоречия в обучающей выборке.

Но, если присмотреться внимательно на строки с ошибками, то можно заметить, что там где они присутствуют вычисленное значение пренебрежительно мало, т.е. порядка одной стотысячной или даже менее. Т.е. там, где в обучающей выборке имели место противоречивые данные, значение на выходе сильно умалено. Если из процентов перевести в пипсы, то получим, что в этих местах, т.е. где следует сидеть на заборе и курить бамбук, изменение котировок менее одного пункта.


Отсюда сам собой напрашивается алгоритм советника:

1. Проверяем наличие открытой позиции по инструменту.

2. Если такая есть, то пытаемся "спрогнозировать" следующее изменение цены. Если нет, то п. 4

3. Если результат прогноза менее 1 пипса или прогнозируемое направление позиции не совпадает с текущим, то открытую позицию необходимо закрыть.

4. Смотрим прогноз на следующий бар. Если его значение превышает спред, то открываем позицию согласно этому самому прогнозу.



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

Время на изучение MQL5, создание советника и даже на его тестирование на демо до 22 сентября еще более чем предостаточно.

Файлы:
test.zip  69 kb
 
Reshetov:

Делаем вот такую проверялку на Java:


У вас коде 63 почти одинаковых строки в целях оптимизации? Цикл развернули?
Причина обращения: