Type/to search
8
Follow
1363
Followers
Một cuộc thảo luận ngắn gọn về xử lý dữ liệu K-line trong giao dịch được lập trình
Discussions
Created 2019-08-13 11:11:38  Updated 2023-10-20 20:06:13
 8
 4968

img

Một cuộc thảo luận ngắn gọn về xử lý dữ liệu K-line trong giao dịch được lập trình

Khi viết các chiến lược giao dịch theo chương trình, sử dụng dữ liệu K-line, thường cần sử dụng một số dữ liệu K-line theo chu kỳ không chuẩn, chẳng hạn như dữ liệu K-line theo chu kỳ 12 phút, dữ liệu K-line theo chu kỳ 4 giờ, thường là loại không chuẩn này Khoảng thời gian không thể lấy được trực tiếp. Vậy chúng ta phản ứng thế nào trước những nhu cầu như vậy?
Câu trả lời chắc chắn là có cách.
Có thể thu được các chu kỳ không chuẩn bằng cách hợp nhất và tổng hợp dữ liệu từ các chu kỳ nhỏ hơn. Bạn có thể tưởng tượng rằng giá cao nhất trong nhiều chu kỳ được tính là giá cao nhất sau khi tổng hợp và giá thấp nhất được tính là giá thấp nhất sau khi tổng hợp. Mở đầu giá sẽ không thay đổi. , giá mở cửa đầu tiên của dữ liệu nguyên liệu của dòng K tổng hợp được sử dụng, giá đóng cửa tương ứng với giá đóng cửa cuối cùng của dữ liệu nguyên liệu của dòng K tổng hợp, thời gian là thời gian của giá mở cửa và khối lượng giao dịch được tính bằng cách cộng tổng khối lượng giao dịch của dữ liệu nguyên liệu thô.
Như thể hiện trong hình ảnh:

  • Ý tưởng

    Chúng tôi lấy thị trường 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 gianCaoMởThấpĐóng
    2019.8.12 00:0011447.0711382.5711367.211406.92
    2019.8.12 01:001142011405.6511366.611373.83
    2019.8.12 02:0011419.2411374.6811365.5111398.19
    2019.8.12 03:0011407.8811398.5911369.711384.71

    Dữ liệu của bốn chu kỳ 1 giờ này được kết hợp thành dữ liệu chu kỳ 4 giờ. Giá mở cửa là giá mở cửa của thời điểm 00:00 đầu tiên: 11382,57
    Giá đóng cửa là giá cuối cùng, tức là giá đóng cửa lúc 03:00: 11384.71
    Giá cao nhất là giá cao nhất ở đây: 11447.07
    Giá thấp nhất ở đây là: 11365.51
    Thời gian bắt đầu của chu kỳ 4 giờ là 00:00, thời gian bắt đầu của dòng K 1 giờ, tức là 2019.8.12 00:00
    Khối lượng giao dịch có thể được tổng hợp sau mỗi 1 giờ (chủ yếu để quan sát cách giá được tổng hợp, điều này không được hiển thị trong dữ liệu khối lượng giao dịch). Tôi sẽ không đi vào chi tiết ở đây.

    Đường K-line 4 giờ tổng hợp là:
    Cao: 11447.07
    Mở: 11382.57
    Thấp: 11365.51
    Đã nhận: 11384.71
    Thời gian: 2019.8.12 00:00

    img

    Bạn có thể thấy dữ liệu rất nhất quán.

  • Viết mã để thực hiện

    Sau khi xác minh những ý tưởng sơ bộ, bạn có thể bắt đầu viết một số mã để triển khai sơ bộ yêu cầu này.

    Phát hành code trực tiếp, code chỉ mang tính chất tham khảo:

    function GetNewCycleRecords (sourceRecords, targetCycle) { // K线合成函数 var ret = [] // 首先获取源K线数据的周期 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++) { // 获取 时区偏移数值 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 } // 测试 function main () { while (true) { var r = exchange.GetRecords() // 原始数据,作为合成K线的基础K线数据,例如要合成4小时K线,可以用1小时K线作为原始数据。 var r2 = GetNewCycleRecords(r, 1000 * 60 * 60 * 4) // 通过 GetNewCycleRecords 函数 传入 原始K线数据 r , 和目标周期, 1000 * 60 * 60 * 4 即 目标合成的周期 是4小时K线数据。 $.PlotRecords(r2, "r2") // 策略类库栏 可以勾选画线类库,调用 $.PlotRecords 画线类库 导出函数 画图。 Sleep(1000) // 每次循环间隔 1000 毫秒,防止访问K线接口获取数据过于频繁,导致交易所限制。 } }

    Trên thực tế, để tổng hợp K-line, cần có hai thứ. Thứ nhất là dữ liệu nguyên liệu, tức là dữ liệu K-line của một chu kỳ nhỏ.var r = exchange.GetRecords()
    Dữ liệu dòng K có chu kỳ nhỏ thu được. Thứ hai là xác định rõ ràng thời kỳ tổng hợp, tức là thời kỳ mục tiêu để tổng hợp dữ liệu dòng K.
    Sau đó, thông qua thuật toán của hàm GetNewCycleRecords, dữ liệu của cấu trúc mảng K-line tổng hợp cuối cùng có thể được trả về.
    Cần lưu ý rằng:

      1. Chu kỳ mục tiêu không thể nhỏ hơn chu kỳ của dòng K mà bạn truyền vào hàm GetNewCycleRecords dưới dạng dữ liệu thô.
        Điều này là do không thể sử dụng một chu kỳ nhỏ để tổng hợp dữ liệu từ một chu kỳ nhỏ hơn.
      1. Khoảng thời gian mục tiêu được đặt ra phải là khoảng thời gian khép kín.
        Đóng chu kỳ là gì?
        Nói một cách đơn giản, trong vòng một giờ hoặc một ngày, các phạm vi thời gian chu kỳ mục tiêu sẽ được kết hợp lại với nhau để tạo thành một vòng lặp khép kín.
        Ví dụ:
        Ví dụ, đường K của chu kỳ 12 phút bắt đầu từ 0:00 của mỗi giờ (lấy 0:00 làm ví dụ) và chu kỳ đầu tiên là00:00:00 ~ 00:12:00, 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 , kéo dài tổng cộng 1 giờ.

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

    Đĩa thực tế đã được chạy:
    img

    So sánh biểu đồ trao đổi
    img

  • Sử dụng dữ liệu K-line để xây dựng cấu trúc dữ liệu cần thiết

    Các thành viên trong nhóm thường đặt câu hỏi: Tôi muốn tính trung bình động của mức giá cao nhất của mỗi K-line thì tôi phải làm thế nào?

    Thông thường, chúng ta tính toán đường trung bình động bằng cách tính trung bình giá đóng cửa để tạo thành đường trung bình động, nhưng đôi khi cần phải tính giá cao nhất, giá thấp nhất, giá mở cửa, v.v.
    Vào lúc này, bạn không thể chỉexchange.GetRecords() Dữ liệu dòng K do hàm trả về được truyền trực tiếp vào hàm tính toán chỉ báo.

    Ví dụ:
    Hàm tính toán chỉ báo trung bình động talib.MA có hai tham số. Tham số đầu tiên là dữ liệu cần truyền vào và tham số thứ hai là tham số chu kỳ chỉ báo.
    Ví dụ, chúng tôi muốn tính toán các chỉ số sau
    img

    Chu kỳ dòng K là 4 giờ.
    Trên biểu đồ trao đổi, một đường trung bình động đã được thiết lập với tham số chu kỳ trung bình động là 9.
    Và nguồn dữ liệu để tính toán được đặt thành mức giá cao nhất của mỗi Thanh.
    img
    Nghĩa là, đường trung bình động này là trung bình của mức giá cao nhất trong 9 thanh K-line 4 giờ, tạo nên đường trung bình động của chỉ báo.

    Chúng ta hãy tự xây dựng một số dữ liệu và xem liệu nó có giống với dữ liệu được tính toán bởi biểu đồ của sàn giao dịch hay 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á trung bình cao nhất của mỗi thanh để có được chỉ báo trung bình động.
    Sau đó, trước tiên bạn cần xây dựng một mảng, trong đó mỗi phần tử dữ liệu tương ứng với giá cao nhất của mỗi thanh.
    Bạn có thể thấy rằng biến highs ban đầu là một mảng rỗng, sau đó chúng ta duyệt qua biến dữ liệu nến r2 (không nhớ r2? Hãy xem mã trong hàm chính tổng hợp nến 4 giờ ở trên).
    Đọc giá cao nhất của mỗi thanh r2 (tức là r2[i].High , i có phạm vi từ 0 đến r2.length - 1 ), sau đó đẩy nó lên mức highs . Theo cách này, một cấu trúc dữ liệu được xây dựng tương ứng một-một với thanh dữ liệu dòng K.

    Tại thời điểm này, giá trị cao có thể được truyền vào hàm talib.MA để tính toán đường 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") // 画出K线 var highs = [] for (var i = 0 ; i < r2.length ; i++) { highs.push(r2[i].High) } var ma = talib.MA(highs, 9) // 用均线指标函数 talib.MA 计算 均线指标 $.PlotLine("high_MA9", ma[ma.length - 2], r2[r2.length - 2].Time) // 使用画线类库把均线指标画在图表上 Sleep(1000) } }

    Chạy thử nghiệm ngược:

    img

    Bạn có thể thấy rằng các giá trị chỉ báo trung bình động tại vị trí 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 "Line Drawing Library" và lưu lại!

  • Làm thế nào để có được dữ liệu K-line trong thị trường tiền kỹ thuật số

    Nền tảng giao dịch định lượng Inventor đã có một giao diện đóng gói, cụ thể là hàm exchange.GetRecords, có thể thu thập dữ liệu K-line.
    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 trao đổi để lấy dữ liệu, vì đôi khi bạn cần chỉ định các tham số để lấy thêm K-line, giao diện GetRecords được đóng gói
    Thông thường sẽ trả về 100. Nếu chiến lược ban đầu yêu cầu hơn 100 dòng K, bạn cần thu thập và chờ đợi.
    Để chiến lược chạy nhanh nhất có thể, bạn có thể tự đóng gói một hàm, truy cập trực tiếp vào giao diện K-line trao đổi và chỉ định các tham số để có thêm dữ liệu K-line.

    Lấy cặp giao dịch BTC_USDT của Huobi làm ví dụ, chúng tôi triển khai yêu cầu này:

    Tìm tài liệu API của sàn giao dịch và xem mô tả về giao diện K-line:
    img

    https://api.huobi.pro/market/history/kline?period=1day&size=200&symbol=btcusdt

    tham số:

    Tên tham sốLoạiBắt buộcMô tảGiá trị
    biểu tượngchuỗiđúngCặp giao dịchbtcusdt, ethbtc...
    periodstringtrueTrả về mức độ chi tiết của dữ liệu thời gian, tức là khoảng thời gian của mỗi nến1 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
    sizeintegerfalseTrả về số lượng dữ liệu K-line[1, 2000]

    Mã kiểm tra:

    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") }

    Phiên bản Python, ví dụ về cách truy cập giao diện sàn giao dịch Huobi:

#!python3 import json import urllib2 def GetRecords_Huobi(period, size, symbol): headers = {'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'} url = "https://api.huobi.pro/market/history/kline?" + "period=" + period + "&size=" + size + "&symbol=" + symbol request = urllib2.Request(url) request.add_header('User-Agent','Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6') opener = urllib2.build_opener() f= opener.open(request) ret = f.read().decode('utf-8') try : jsonData = json.loads(ret) records = [] for i in range(len(jsonData["data"]) - 1, -1, -1): records.append({ "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 except Exception as e: Log(e) def main(): r = GetRecords_Huobi("1day", "300", "btcusdt") Log(len(r)) ext.PlotRecords(r, "K") # 需要引用Python画线类库

Phiên bản Python, ví dụ về cách truy cập giao diện K-line của Binance Exchange:

#!python3 import json import urllib2 def GetRecords_Huobi(period, size, symbol): headers = {'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'} url = "https://api.binance.com/api/v3/klines?symbol=" + symbol + "&interval=" + period request = urllib2.Request(url) request.add_header('User-Agent','Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6') opener = urllib2.build_opener() f= opener.open(request) ret = f.read().decode('utf-8') try : jsonData = json.loads(ret) records = [] for i in range(len(jsonData)): records.append({ "Time" : float(jsonData[i][0]), "High" : float(jsonData[i][2]), "Open" : float(jsonData[i][1]), "Low" : float(jsonData[i][3]), "Close" : float(jsonData[i][4]), "Volume" : float(jsonData[i][5]), }) return records except Exception as e: Log(e) def main(): r = GetRecords_Huobi("1m", "300", "BTCUSDT") Log(len(r)) ext.PlotRecords(r, "K") # 需要引用Python画线类库

img

img

Chúng ta có thể thấy trong nhật ký rằng records.length là 300, điều đó có nghĩa là có 300 thanh dữ liệu K-line.
img

Related Recommendations
Comment
All comments (8)

    贴主能修复一下问题么?无法用3小时或6小时k合成日k

    6 years ago

    好的,抽时间改改。

    6 years ago

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

    这一句有问题,无法用3小时或6小时k合成日k,只能用1小时,2小时,4小时的k线合成日k

    6 years ago

    如果要爬某品种全部的历史数据也能爬么?

    6 years ago

    这是访问交易所接口数据的,交易所给你多少数据就是多少。也就是最近的几百根吧一般来说。

    6 years ago

    感谢回复

    7 years ago

    请问,如果想要超过300根,怎么处理比较好呢?比如1000根K线数据。交易所单次好像支持每次300根。多谢

    7 years ago

    如果 超过交易所接口支持的最大返回数量,这样只能收集数据,等足够K线数据量。

    7 years ago
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)