Xử lý dữ liệu dòng K trong giao dịch định lượng

Tác giả:Tốt, Tạo: 2019-09-03 11:15:30, Cập nhật: 2023-11-07 20:43:41

img

Làm thế nào để K Line xử lý dữ liệu trong giao dịch định lượng?

Khi viết một chiến lược giao dịch định lượng, sử dụng dữ liệu đường K, thường có trường hợp mà dữ liệu đường K chu kỳ không chuẩn được yêu cầu. ví dụ, dữ liệu đường K chu kỳ 12 phút và dữ liệu chu kỳ đường K 4 giờ được yêu cầu. Thông thường các chu kỳ không chuẩn như vậy không trực tiếp có sẵn. Vậy làm thế nào để chúng ta giải quyết những nhu cầu như vậy?

Dữ liệu đường K chu kỳ không chuẩn có thể được thu được bằng cách kết hợp dữ liệu của chu kỳ nhỏ hơn. Hình ảnh này, giá cao nhất trong nhiều chu kỳ được tính là giá cao nhất sau tổng hợp đường K chu kỳ nhiều, và giá thấp nhất được tính là giá thấp nhất sau tổng hợp, và giá mở không thay đổi. Giá mở đầu tiên của dữ liệu nguyên liệu của đường K được tổng hợp. Giá đóng tương ứng với giá đóng của dữ liệu nguyên liệu cuối cùng của đường K. Thời gian sử dụng thời gian của đường giá mở k. Khối lượng giao dịch sử dụng dữ liệu nguyên liệu tổng hợp và tính toán.

Như trong hình:

  • Suy nghĩ

Hãy lấy tài sản blockchain BTC_USDT làm ví dụ và tổng hợp 1 giờ thành 4 giờ.

img img img img

Thời gian cao nhất Mở Tối thiểu nhất Gắn lại
2019.8.12 00:00 11447.07 11382.57 11367.2 11406.92
2019.8.12 01:00 11420 11405.65 11366.6 11373.83
2019.8.12 02:00 11419.24 11374.68 11365.51 11398.19
2019.8.12 03:00 11407.88 11398.59 11369.7 11384.71

Dữ liệu của bốn chu kỳ 1 giờ được kết hợp thành một dữ liệu chu kỳ 4 giờ duy nhất.

Giá mở là giá mở đầu tiên K dòng tại 00:00 thời gian: 11382.57 Giá đóng là giá đóng k dòng cuối cùng lúc 03:00: 11384.71 Giá cao nhất là tìm giá cao nhất trong số họ: 11447.07 Giá thấp nhất là tìm giá thấp nhất trong số họ: 11365.51

Lưu ý: Thị trường tương lai hàng hóa Trung Quốc đóng cửa lúc 15:00 vào một ngày giao dịch bình thường

Thời gian bắt đầu chu kỳ 4 giờ là thời gian bắt đầu của đường K 1 giờ đầu tiên, tức là 2019.8.12 00:00

Tổng khối lượng của tất cả các dòng k 1 giờ được sử dụng như khối lượng dòng k 4 giờ này.

Một dòng K 4 giờ được tổng hợp:

High: 11447.07
Open: 11382.57
Low: 11365.51
Close: 11384.71
Time: 209.8.12 00:00

img

Bạn có thể thấy rằng dữ liệu là phù hợp.

  • Thực hiện mã

Sau khi hiểu được những ý tưởng ban đầu, bạn có thể tự viết mã để thực hiện các yêu cầu.

Mã này chỉ dùng để tham khảo:

function GetNewCycleRecords (sourceRecords, targetCycle) { // K line synthesis function
      var ret = []
      
      // First get the source K line data cycle
      if (!sourceRecords || sourceRecords.length < 2) {
          Return null
      }
      var sourceLen = sourceRecords.length
      var sourceCycle = sourceRecords[sourceLen - 1].Time - sourceRecords[sourceLen - 2].Time

      if (targetCycle % sourceCycle != 0) {
          Log("targetCycle:", targetCycle)
          Log("sourceCycle:", sourceCycle)
          throw "targetCycle is not an integral multiple of sourceCycle."
      }

      if ((1000 * 60 * 60) % targetCycle != 0 && (1000 * 60 * 60 * 24) % targetCycle != 0) {
          Log("targetCycle:", targetCycle)
          Log("sourceCycle:", sourceCycle)
          Log((1000 * 60 * 60) % targetCycle, (1000 * 60 * 60 * 24) % targetCycle)
          throw "targetCycle cannot complete the cycle."
      }

      var multiple = targetCycle / sourceCycle


      var isBegin = false
      var count = 0
      var high = 0
      var low = 0
      var open = 0
      var close = 0
      var time = 0
      var vol = 0
      for (var i = 0 ; i < sourceLen ; i++) {
          // Get the time zone offset value
          var d = new Date()
          var n = d.getTimezoneOffset()

          if ((1000 * 60 * 60 * 24) - sourceRecords[i].Time % (1000 * 60 * 60 * 24) + (n * 1000 * 60)) % targetCycle == 0) {
              isBegin = true
          }

          if (isBegin) {
              if (count == 0) {
                  High = sourceRecords[i].High
                  Low = sourceRecords[i].Low
                  Open = sourceRecords[i].Open
                  Close = sourceRecords[i].Close
                  Time = sourceRecords[i].Time
                  Vol = sourceRecords[i].Volume

                  count++
              } else if (count < multiple) {
                  High = Math.max(high, sourceRecords[i].High)
                  Low = Math.min(low, sourceRecords[i].Low)
                  Close = sourceRecords[i].Close
                  Vol += sourceRecords[i].Volume

                  count++
              }

              if (count == multiple || i == sourceLen - 1) {
                  Ret.push({
                      High : high,
                      Low : low,
                      Open : open,
                      Close : close,
                      Time : time,
                      Volume : vol,
                  })
                  count = 0
              }
          }
      }

      Return ret
  }

  // test
  function main () {
      while (true) {
          var r = exchange.GetRecords() // Raw data, as the basic K-line data of the synthesize K line. for example, to synthesize a 4-hour K-line, you can use the 1-hour K-line as the raw data.
          var r2 = GetNewCycleRecords(r, 1000 * 60 * 60 * 4) // Pass the original K-line data r through the GetNewCycleRecords function, and the target cycles, 1000 * 60 * 60 * 4, ie the target synthesis cycle is 4 hours K-line data .

          $.PlotRecords(r2, "r2") // The strategy class library bar can be selected by check the line class library, and calling the $.PlotRecords line drawing class library to export the function drawing.
          Sleep(1000) // Each cycle is separated by 1000 milliseconds, preventing access to the K-line interface too much, resulting in transaction restrictions.
      }
  }

Trong thực tế, để tổng hợp đường K, bạn cần hai thứ. thứ nhất là dữ liệu nguyên liệu thô, nghĩa là dữ liệu đường K của một chu kỳ nhỏ hơn. trong ví dụ này, nó làvar r = exchange.GetRecords()để có được dữ liệu đường K chu kỳ nhỏ hơn.

Thứ hai là để tìm ra kích thước của chu kỳ tổng hợp, chúng tôi sử dụng thuật toán chức năng GetNewCycleRecords để làm điều này, sau đó bạn cuối cùng có thể trả về dữ liệu của một cấu trúc mảng K-line tổng hợp.

Xin lưu ý:

  1. Chu kỳ mục tiêu không thể nhỏ hơn chu kỳ của đường K mà bạn đã vượt qua trong chức năng GetNewCycleRecords như một nguyên liệu thô cho dữ liệu. Bởi vì bạn không thể tổng hợp dữ liệu chu kỳ nhỏ hơn bằng một chu kỳ lớn hơn. chỉ ngược lại.

  2. Chu kỳ mục tiêu phải được đặt thành cycle closed. cycle closed là gì? Nói đơn giản, trong vòng một giờ hoặc trong vòng một ngày, các khoảng thời gian chu kỳ mục tiêu được kết hợp để tạo thành một vòng lặp đóng.

ví dụ:

Dòng K của chu kỳ 12 phút bắt đầu từ 0:0 mỗi giờ, chu kỳ đầu tiên là 00:00:00 ~ 00:12:00, và chu kỳ thứ hai là 00:12: 00 ~ 00: 24:00, chu kỳ thứ ba là 00:24: 00 ~ 00:36:00, chu kỳ thứ tư là 00:36:00 ~ 00:48:00, chu kỳ thứ năm là 00:48 :00 ~ 01:00:00, chính xác là một giờ hoàn thành.

Nếu nó là một chu kỳ 13 phút, nó sẽ là một chu kỳ không đóng. Dữ liệu được tính bằng chu kỳ như vậy không phải là duy nhất vì dữ liệu tổng hợp khác nhau tùy thuộc vào điểm khởi đầu của dữ liệu tổng hợp.

Chạy nó trên thị trường thực tế:

img

Biểu đồ trao đổi tương phản

img

  • Xây dựng cấu trúc dữ liệu yêu cầu bằng cách sử dụng dữ liệu đường K

Tôi muốn tính trung bình động của giá cao nhất cho tất cả các đường K. Tôi nên làm gì?

Thông thường, chúng tôi tính toán các đường trung bình động bằng cách sử dụng giá trung bình của giá đóng cửa, nhưng đôi khi có nhu cầu sử dụng giá cao nhất, giá thấp nhất, giá mở cửa và vân vân.

Đối với các yêu cầu bổ sung này, dữ liệu đường K được trả về bởi hàm exchange.GetRecords (()) không thể được truyền trực tiếp đến hàm tính toán chỉ số.

Ví dụ: Cáctalib.MAChức năng tính toán chỉ số trung bình động có hai tham số, một là dữ liệu cần được truyền vào và thứ hai là tham số chu kỳ chỉ số.

ví dụ, chúng ta cần tính toán các chỉ số như được hiển thị dưới đây.

img

Chu kỳ đường K là 4 giờ.

Trên biểu đồ báo giá thị trường chứng khoán, một đường trung bình đã được thiết lập với tham số chu kỳ là 9.

Nguồn dữ liệu được tính toán sử dụng giá cao nhất cho mỗi Bar.

img

Đó là, đường trung bình động này bao gồm trung bình của giá trung bình cao nhất của chín 4-giờ chu kỳ K-line Bar.

Chúng ta hãy tự xây dựng một dữ liệu để xem liệu nó có giống nhau với dữ liệu của sàn giao dịch không.

var highs = []
for (var i = 0 ; i < r2.length ; i++) {
    highs.push(r2[i].High)
}

Vì chúng ta cần tính toán giá cao nhất của mỗi Bar để có được giá trị của chỉ số trung bình động, chúng ta cần xây dựng một mảng trong đó mỗi yếu tố dữ liệu có giá cao nhất cho mỗi Bar.

Bạn có thể thấy rằnghighsbiến là ban đầu một mảng trống, sau đó chúng ta đi qua biến dữ liệu r2 k-line (không nhớ r2? Hãy nhìn vào mã trong hàm chính tổng hợp 4-hour K-line ở trên).

Đọc giá cao nhất của mỗi Bar của r2 (tức là r2[i].High, i dao động từ 0 đến r2.length - 1), sau đó nhấn vàohighsBằng cách này chúng ta chỉ cần xây dựng một cấu trúc dữ liệu tương ứng một-một với K-đường dữ liệu thanh.

Vào lúc này,highscó thể vượt quatalib.MAchức năng để tính trung bình động.

Ví dụ đầy đủ:

function main () {
     while (true) {
         var r = exchange.GetRecords()
         var r2 = GetNewCycleRecords(r, 1000 * 60 * 60 * 4)
         if (!r2) {
             Continue
         }
        
         $.PlotRecords(r2, "r2") // Draw the K line
        
         var highs = []
         for (var i = 0 ; i < r2.length ; i++) {
             Highs.push(r2[i].High)
         }
        
         var ma = talib.MA(highs, 9) // use the moving average function "talib.MA" to calculate the moving average indicator
         $.PlotLine("high_MA9", ma[ma.length - 2], r2[r2.length - 2].Time) // Use the line drawing library to draw the moving average indicator on the chart
        
         Sleep(1000)
     }
}

Kiểm tra hậu quả:

img

Bạn có thể thấy rằng giá trị chỉ số trung bình của vị trí điểm chuột trong hình là 11466.9289

Mã ở trên có thể được sao chép vào chiến lược để chạy thử nghiệm, hãy nhớ kiểm tra thư viện đường vẽ và lưu nó!

  • Phương pháp thu thập dữ liệu K-line cho thị trường tiền điện tử

Nền tảng FMZ Quant đã có một giao diện đóng gói, cụ thể làexchange.GetRecordschức năng, để có được dữ liệu đường K.

Sau đây tập trung vào việc truy cập trực tiếp vào giao diện dữ liệu K-line của trao đổi để lấy dữ liệu, bởi vì đôi khi bạn cần phải chỉ định các tham số để có được nhiều hơn K dòng, góiGetRecordsgiao diện thường trả về 100 k dòng. nếu bạn gặp một chiến lược ban đầu đòi hỏi hơn 100 K-dòng, bạn cần phải chờ quá trình thu thập.

Để làm cho chiến lược hoạt động càng sớm càng tốt, bạn có thể đóng gói một hàm, truy cập trực tiếp vào giao diện đường K của sàn giao dịch, và chỉ định các tham số để có được nhiều dữ liệu đường K hơn.

Sử dụng cặp giao dịch BTC_USDT trên sàn giao dịch Huobi làm ví dụ, chúng tôi thực hiện yêu cầu sau:

Tìm tài liệu API của trao đổi và xem mô tả giao diện K-line:

img

https://huobiapi.github.io/docs/spot/v1/en/#get-klines-candles

Các thông số:

Tên Loại Có cần thiết? Mô tả Giá trị
biểu tượng chuỗi đúng Cặp giao dịch Btcusdt, ethbtc...
thời gian chuỗi đúng Trả về độ chi tiết thời gian của dữ liệu, đó là khoảng thời gian của mỗi dòng k 1 phút, 5 phút, 15 phút, 30 phút, 60 phút, 1 ngày, 1 tháng, 1 tuần, 1 năm
kích thước số nguyên sai Trả về số K dòng dữ liệu [1, 2000]

Mã thử nghiệm:

function GetRecords_Huobi (period, size, symbol) {
    var url = "https://api.huobi.pro/market/history/kline?" + "period=" + period + "&size=" + size + "&symbol=" + symbol
    var ret = HttpQuery(url)
    
    try {
        var jsonData = JSON.parse(ret)
        var records = []
        for (var i = jsonData.data.length - 1; i >= 0 ; i--) {
            records.push({
                Time : jsonData.data[i].id * 1000,
                High : jsonData.data[i].high,
                Open : jsonData.data[i].open,
                Low : jsonData.data[i].low,
                Close : jsonData.data[i].close,
                Volume : jsonData.data[i].vol,
            })
        }
        return records
    } catch (e) {
        Log(e)
    }
}  


function main() {
    var records = GetRecords_Huobi("1day", "300", "btcusdt")
    Log(records.length)
    $.PlotRecords(records, "K")
}

img img

Bạn có thể thấy trên nhật ký, inrecords.lengthlà 300, nghĩa là số lượngrecordsDây dữ liệu đường K là 300.img


Có liên quan

Thêm nữa