4
Подписаться
1271
Подписчики

Научить вас, как трансплантировать языковую стратегию (продвинутый уровень)

Создано: 2019-11-13 09:15:56, Обновлено: 2024-12-15 16:02:09
comments   0
hits   2645

Научить вас, как трансплантировать языковую стратегию (продвинутый уровень)

Научить вас, как трансплантировать языковую стратегию (продвинутый уровень)

Предыдущая статьяНаучите вас, как писать стратегии шаг за шагом - пересадите мою языковую стратегиюВ статье мы провели тест трансплантации на простой стратегии языка Mai. Если это немного более сложная стратегия языка Mai, как трансплантировать ее на язык JavaScript? Какие методы для этого существуют?

Давайте сначала рассмотрим стратегию, которую следует применить на этот раз:

(*backtest
start: 2019-05-01 00:00:00
end: 2019-11-12 00:00:00
period: 1d
exchanges: [{"eid":"Futures_OKCoin","currency":"BTC_USD"}]
args: [["SlideTick",10,126961],["ContractType","quarter",126961]]
*)

N1:=10;
N2:=21;
AP:=(HIGH+LOW+CLOSE)/3;
ESA:=EMA(AP,N1);
D:=EMA(ABS(AP-ESA),N1);
CI:=(AP-ESA)/(0.015*D);
TCI:=EMA(CI,N2);
WT1:TCI;
WT2:SMA(WT1,4,1);
AA:=CROSS(WT1,WT2);
BB:=CROSSDOWN(WT1,WT2);
REF(AA,1),BPK;
REF(BB,1),SPK;

Начало этой языковой стратегии(*backtest...*)Это код конфигурации настройки бэктеста. Для облегчения сравнения устанавливается унифицированная конфигурация бэктеста. Эта стратегия также является случайно найденной стратегией, она не слишком сложна (по сравнению с стратегией в предыдущей статье) и является более репрезентативной. Чтобы пересадить стратегию языка Mai, вы должны сначала прочитать содержание стратегии. Код стратегии языка Mai относительно лаконичен, и в основном вы можете иметь определенное понимание общей стратегии. Эта стратегия использует несколько функций индикатора.EMASMA

Сначала постройте колесо

  • EMA Данная функция индикатора имеет готовую функцию библиотеки индикаторов при написании стратегий на языке JavaScript на платформе FMZ. Прямо сейчас:TA.MA

  • SMA Что нам нужно сделать, так этоSMAМы обнаружили, что функция индикатора SMA не поддерживается в библиотеке TA FMZ. Также есть различия между индикатором SMA в библиотеке talib и в языке Mai: Научить вас, как трансплантировать языковую стратегию (продвинутый уровень) Как видите, в дополнение к параметру периода в части параметров есть также параметр веса.

Описание функции индикатора SMA в библиотеке talib в документации FMZ API следующее: Научить вас, как трансплантировать языковую стратегию (продвинутый уровень)

видимыйtalib.SMAПростой индикатор скользящей средней. Таким образом, вы можете реализовать только один вариант самостоятельно.SMAКак разработчик, пишущий стратегии на языке Javascript, это также один из необходимых навыков. В конце концов, если нет готовых колес, машину все равно нужно водить, так что просто постройте одно.

Честно говоря, не так много исследований по индикаторам и т. п. Обычно, если я чего-то не понимаю, я просто ищу и выискиваю информацию. Для СМА мы обнаружили следующее: Научить вас, как трансплантировать языковую стратегию (продвинутый уровень)

Я считаю, что описанный здесь алгоритмический процесс вполне надежен. Давайте реализуем его:

  function SMA (arr, n, m) {
      var sma = []
      var currSMA = null
      for (var i = 0; i < arr.length; i++) {
          if (arr[i] && !isNaN(arr[i])) {
              if (!currSMA) {
                  currSMA = arr[i]
                  sma.push(currSMA)
                  continue
              }  

              // [M*C2+(N-M)*S1]/N
              currSMA = (m * arr[i] + (n - m) * currSMA) / n
              sma.push(currSMA)
          } else {
              sma.push(NaN)
          }
      }  

      return sma
  }

Написание раздела «Заполнение»

Использование рамок политикиНаучите вас, как писать стратегии шаг за шагом - пересадите мою языковую стратегиюВ статье одна и та же структура в основном заполняет две части: Научить вас, как трансплантировать языковую стратегию (продвинутый уровень)

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

Мы рассмотрим функции языка май по порядку:

  • 1、AP:=(HIGH+LOW+CLOSE)/3;

Это предложение можно понимать как сложение самой высокой цены, самой низкой цены и цены закрытия каждого БАРА в данных K-линии и деление этого на 3, вычисление среднего значения и последующее сохранение его в виде массива, соответствующего каждому БАРУ по одному один. Это можно сделать следующим образом:

  function CalcAP (r) {   // AP:=(HIGH+LOW+CLOSE)/3;
      var arrAP = []      // 声明一个空数组

      for (var i = 0; i < r.length; i++) {      // r为传入的K线数据,是一个数组,用for遍历这个数组
          v = (r[i].High + r[i].Low + r[i].Close) / 3      // 计算 平均值
          arrAP.push(v)                                    // 添加在 arrAP数组的尾部,arrAP是空的时候尾部就是第一个。
      }  

      return arrAP     // 返回 这个平均值数组,即麦语言中计算的 AP 
  }

Просто вызовите эту функцию в основном цикле функции OnTick, например:

  // 计算指标
  // AP
  var ap = CalcAP(records)
  • 2. После завершения расчета AP продолжайте расчетESA:=EMA(AP,N1);:

Здесь нам нужно использовать данные AP, рассчитанные на предыдущем шаге, чтобы вычислить ESA. Фактически, этот ESA является “экспоненциальным скользящим средним” AP, то есть индикатором EMA, поэтому мы используем AP в качестве данных и N1 в качестве параметр индикатора EMA для расчета индикатора EMA.

  function CalcESA (ap, n1) {   // ESA:=EMA(AP,N1);
      if (ap.length <= n1) {    // 如果AP的长度小于指标参数,是无法计算出有效数据的,这个时候让函数返回false。
          return false
      }  

      return TA.EMA(ap, n1)
  }
  • 3、D:=EMA(ABS(AP-ESA),N1);

Используйте рассчитанноеAPESAРассчитать данныеD。 Вы можете ознакомиться с комментариями к коду здесь, чтобы получить некоторые советы по расчету индикаторов.

  function CalcD (ap, esa, n1) {    // D:=EMA(ABS(AP-ESA),N1);
      var arrABS_APminusESA = []
      if (ap.length != esa.length) {
          throw "ap.length != esa.length"
      }  

      for (var i = 0; i < ap.length; i++) {
          // 计算指标数值时,必须判断一下数据的有效性,因为前几次EMA计算可能数组中的开始部分的数据是NaN,或者null
          // 所以必须判断,参与计算的数据都是有效数值才能进行,如果有任何无效数值,就用NaN向arrABS_APminusESA填充
          // 这样计算得到的数据,每个位置和之前的数据都是一一对应的,不会错位。
          if (ap[i] && esa[i] && !isNaN(ap[i]) && !isNaN(esa[i])) {
              v = Math.abs(ap[i] - esa[i])     // 根据ABS(AP-ESA) , 具体计算数值,然后放入arrABS_APminusESA数组
              arrABS_APminusESA.push(v)
          } else {
              arrABS_APminusESA.push(NaN)
          }
      }  

      if (arrABS_APminusESA.length <= n1) {
          return false
      }  

      return TA.EMA(arrABS_APminusESA, n1)    // 计算数组arrABS_APminusESA的EMA指标,得到数据D(数组结构)
  }
  • 4、CI:=(AP-ESA)/(0.015*D); Этот метод расчета аналогичен шагу 1, и код выпускается напрямую.
  function CalcCI (ap, esa, d) {    // CI:=(AP-ESA)/(0.015*D);
      var arrCI = []
      if (ap.length != esa.length || ap.length != d.length) {
          throw "ap.length != esa.length || ap.length != d.length"
      }
      for (var i = 0; i < ap.length; i++) {
          if (ap[i] && esa[i] && d[i] && !isNaN(ap[i]) && !isNaN(esa[i]) && !isNaN(d[i])) {
              v = (ap[i] - esa[i]) / (0.015 * d[i])
              arrCI.push(v)
          } else {
              arrCI.push(NaN)
          }
      }  

      if (arrCI.length == 0) {
          return false
      }  

      return arrCI
  }
  • TCI:=EMA(CI,N2); Просто рассчитайте индикатор EMA для массива CI.
  function CalcTCI (ci, n2) {   // TCI:=EMA(CI,N2);
      if (ci.length <= n2) {
          return false
      }  

      return TA.EMA(ci, n2)
  }
  • WT2:SMA(WT1,4,1);

На этом последнем этапе мы используем колесо, которое построили ранее.SMAфункция.

  function CalcWT2 (wt1) {    // WT2:SMA(WT1,4,1);
      if (wt1.length <= 4) {
          return false 
      }  

      return SMA(wt1, 4, 1)   // 使用我们自己实现的SMA函数计算出wt1的SMA指标。
  }

Трансплантация торговых сигналов очень проста.

AA:=CROSS(WT1,WT2);
BB:=CROSSDOWN(WT1,WT2);
REF(AA,1),BPK;
REF(BB,1),SPK;

Читая эти предложения кода языка май, мы можем узнать, что золотой крест и мертвый крест двух индикаторных линий WT1 и WT2 используются в качестве условий для открытия позиции. Следует отметить, что используется предыдущий сигнал пересечения. Проведите прямое бэктестирование стратегии с помощью языка микрофона, и мы увидим: Научить вас, как трансплантировать языковую стратегию (продвинутый уровень)

Благодаря фактическому функционированию стратегии языка май можно увидеть, что при обнаружении сигнала в точке открытия фактически определяется, является ли позиция за 2 бара до точки открытия золотым крестом. Это хорошо видно из рисунка выше: Научить вас, как трансплантировать языковую стратегию (продвинутый уровень) Научить вас, как трансплантировать языковую стратегию (продвинутый уровень)

Код заполнения части обнаружения сигнала можно записать так:

if ((_State == IDLE || _State == SHORT) && wt1[wt1.length - 4] < wt2[wt2.length - 4] && wt1[wt1.length - 3] > wt2[wt2.length - 3]) {
    if (_State == IDLE) {
        _State = OPENLONG
        Log("OPENLONG")    // 测试
    }
    if (_State == SHORT) {
        _State = COVERSHORT
        Log("COVERSHORT")  // 测试
    }
    isOK = false  
}

if ((_State == IDLE || _State == LONG) && wt1[wt1.length - 4] > wt2[wt2.length - 4] && wt1[wt1.length - 3] < wt2[wt2.length - 3]) {
    if (_State == IDLE) {
        _State = OPENSHORT
        Log("OPENSHORT")  // 测试
    }
    if (_State == LONG) {
        _State = COVERLONG
        Log("COVERLONG")  // 测试
    }
    isOK = false   
}

Здесь мы можем подумать о том, почему инструкции SPK и BPK языка Mai можно реализовать с помощью приведенного выше кода.

Бэктестинг

Конфигурация бэктеста: Научить вас, как трансплантировать языковую стратегию (продвинутый уровень)

Тестирование версии на языке Mai: Научить вас, как трансплантировать языковую стратегию (продвинутый уровень)

Тестирование версии JavaScript: Научить вас, как трансплантировать языковую стратегию (продвинутый уровень) Научить вас, как трансплантировать языковую стратегию (продвинутый уровень)

Код в начале функции OnTick используется для ускорения процесса бэктестинга и запуска стратегии на основе модели цены закрытия. Если вам интересно, вы можете проанализировать его подробно.

function OnTick(){
    // 驱动策略的行情处理部分
    var records = _C(exchange.GetRecords)
    if (records[records.length - 1].Time == preTime) {
        if (isOK) {
            Sleep(500)
            return 
        }
    } else {
        preTime = records[records.length - 1].Time
    }
    ...
    ..
    .

Полный код стратегии обучения: https://www.fmz.com/strategy/174457

Спасибо за прочтение