avatar of 发明者量化-小小梦 发明者量化-小小梦
tập trung vào tin nhắn riêng tư
4
tập trung vào
1271
Người theo dõi

Dạy bạn cách ghép một chiến lược ngôn ngữ (nâng cao)

Được tạo ra trong: 2019-11-13 09:15:56, cập nhật trên: 2024-12-15 16:02:09
comments   0
hits   2645

Dạy bạn cách ghép một chiến lược ngôn ngữ (nâng cao)

Dạy bạn cách ghép một chiến lược ngôn ngữ (nâng cao)

Bài viết trướcDạy bạn cách viết chiến lược từng bước - ghép một chiến lược ngôn ngữ của tôiTrong bài viết, chúng tôi đã tiến hành thử nghiệm ghép trên một chiến lược ngôn ngữ Mai đơn giản. Nếu là một chiến lược ngôn ngữ Mai phức tạp hơn một chút, làm thế nào để ghép nó vào ngôn ngữ JavaScript? Các kỹ thuật cho việc này là gì?

Trước tiên chúng ta hãy xem xét chiến lược cấy ghép lần này:

(*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;

Sự khởi đầu của chiến lược ngôn ngữ này(*backtest...*)Đây là mã cấu hình của thiết lập backtest. Để tạo điều kiện so sánh, một cấu hình backtest thống nhất được thiết lập. Chiến lược này cũng là một chiến lược được tìm thấy ngẫu nhiên, không quá phức tạp (so với chiến lược trong bài viết trước) và mang tính đại diện hơn. Để ghép một chiến lược ngôn ngữ Mai, trước tiên bạn phải đọc nội dung chiến lược. Mã chiến lược ngôn ngữ Mai tương đối súc tích, về cơ bản bạn có thể hiểu được một số chiến lược tổng thể. Chiến lược này sử dụng một số hàm chỉ báo.EMASMA

Đầu tiên hãy xây dựng một bánh xe

  • EMA Chức năng chỉ báo này có thư viện chỉ báo có sẵn khi viết chiến lược bằng ngôn ngữ JavaScript trên nền tảng FMZ. Ngay lập tức:TA.MA

  • SMA Những gì chúng ta cần làm làSMAChúng tôi thấy rằng chức năng chỉ báo SMA không được hỗ trợ trong thư viện TA của FMZ. Cũng có sự khác biệt giữa chỉ báo SMA trong thư viện talib và trong ngôn ngữ Mai: Dạy bạn cách ghép một chiến lược ngôn ngữ (nâng cao) Như bạn có thể thấy, ngoài tham số chu kỳ, còn có tham số trọng số trong phần tham số.

Mô tả về chức năng chỉ báo SMA trong thư viện talib trong tài liệu API FMZ như sau: Dạy bạn cách ghép một chiến lược ngôn ngữ (nâng cao)

dễ thấytalib.SMALà một chỉ báo trung bình động đơn giản. Theo cách này, bạn chỉ có thể tự mình thực hiện mộtSMALà một nhà phát triển viết chiến lược sử dụng ngôn ngữ Javascript, đây cũng là một trong những kỹ năng cần thiết. Rốt cuộc, nếu không có bánh xe làm sẵn, chiếc xe vẫn cần phải được lái, vì vậy chỉ cần chế tạo một chiếc.

Thành thật mà nói, không có nhiều nghiên cứu về các chỉ số và những thứ tương tự. Nói chung, nếu tôi không hiểu điều gì đó, tôi chỉ tìm kiếm và tra cứu thông tin. Đối với SMA, chúng tôi thấy như sau: Dạy bạn cách ghép một chiến lược ngôn ngữ (nâng cao)

Tôi cảm thấy rằng quá trình thuật toán được mô tả ở đây khá đáng tin cậy. Hãy triển khai nó:

  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
  }

Viết phần điền

Sử dụng Khung Chính sáchDạy bạn cách viết chiến lược từng bước - ghép một chiến lược ngôn ngữ của tôiCùng một khuôn khổ trong bài viết chủ yếu bao gồm hai phần: Dạy bạn cách ghép một chiến lược ngôn ngữ (nâng cao)

Đầu tiên, xử lý dữ liệu thị trường và tính toán chỉ số. Dạy bạn cách ghép một chiến lược ngôn ngữ (nâng cao)

Chúng ta sẽ lần lượt tìm hiểu các chức năng của tiếng Mai:

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

Câu này có thể hiểu là cộng giá cao nhất, giá thấp nhất và giá đóng cửa của mỗi BAR trong dữ liệu K-line và chia cho 3, tính giá trị trung bình, sau đó lưu trữ dưới dạng một mảng, tương ứng với mỗi BAR một một. Có thể xử lý như thế này:

  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 
  }

Chỉ cần gọi hàm này trong vòng lặp chính là hàm OnTick, ví dụ:

  // 计算指标
  // AP
  var ap = CalcAP(records)
  • 2. Sau khi tính toán AP xong, tiếp tục tính toánESA:=EMA(AP,N1);:

Ở đây chúng ta cần sử dụng dữ liệu AP được tính toán ở bước trước để tính ESA. Trên thực tế, ESA này là “trung bình động theo cấp số nhân” của AP, tức là chỉ báo EMA, vì vậy chúng ta sử dụng AP làm dữ liệu và N1 làm tham số của chỉ báo EMA để tính toán chỉ báo 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);

Sử dụng tính toánAPESATính toán dữ liệuD。 Bạn có thể xem phần chú thích mã ở đây để biết một số mẹo về tính toán chỉ báo.

  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); Phương pháp tính toán này tương tự như bước 1 và mã được phát hành trực tiếp.
  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); Chỉ cần tính toán chỉ số EMA cho mảng 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);

Bước cuối cùng này sử dụng bánh xe mà chúng ta đã xây dựng trước đó.SMAchức năng.

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

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

Việc cấy ghép tín hiệu giao dịch rất đơn giản.

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

Đọc những câu này của mã ngôn ngữ Mai, chúng ta có thể biết rằng sự phán đoán chữ thập vàng và chữ thập chết của hai đường chỉ báo WT1 và WT2 được sử dụng làm điều kiện để mở một vị thế. Cần lưu ý rằng tín hiệu chữ thập trước đó được sử dụng. Kiểm tra trực tiếp chiến lược bằng ngôn ngữ micrô và chúng ta quan sát thấy: Dạy bạn cách ghép một chiến lược ngôn ngữ (nâng cao)

Thông qua hoạt động thực tế của Chiến lược ngôn ngữ Mai, có thể thấy rằng khi phát hiện tín hiệu tại điểm mở, thực chất nó đang phát hiện xem vị trí 2 BAR trước điểm mở có phải là điểm giao cắt vàng hay không. Có thể thấy rõ điều này từ hình trên: Dạy bạn cách ghép một chiến lược ngôn ngữ (nâng cao) Dạy bạn cách ghép một chiến lược ngôn ngữ (nâng cao)

Mã điền của phần phát hiện tín hiệu có thể được viết như sau:

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   
}

Ở đây chúng ta có thể suy nghĩ về lý do tại sao các lệnh SPK và BPK của ngôn ngữ Mai có thể được triển khai bằng mã trên.

Kiểm tra ngược

Cấu hình kiểm tra ngược: Dạy bạn cách ghép một chiến lược ngôn ngữ (nâng cao)

Phiên bản ngôn ngữ Mai kiểm tra lại: Dạy bạn cách ghép một chiến lược ngôn ngữ (nâng cao)

Kiểm tra phiên bản JavaScript: Dạy bạn cách ghép một chiến lược ngôn ngữ (nâng cao) Dạy bạn cách ghép một chiến lược ngôn ngữ (nâng cao)

Mã ở đầu hàm OnTick được sử dụng để tăng tốc quá trình kiểm tra ngược và chạy chiến lược dựa trên mô hình giá đóng cửa. Nếu bạn quan tâm, bạn có thể phân tích chi tiết.

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
    }
    ...
    ..
    .

Mã chiến lược giảng dạy hoàn chỉnh: https://www.fmz.com/strategy/174457

Cảm ơn bạn đã đọc