Kinh nghiệm phát triển chiến lược giao dịch

Tác giả:Tốt, Tạo: 2019-09-05 11:49:31, Cập nhật: 2023-11-07 20:48:06

img

Mục đích của bài viết này là mô tả một số kinh nghiệm trong phát triển chiến lược, cũng như một số mẹo, cho phép độc giả nhanh chóng nắm bắt được điểm chính của phát triển chiến lược giao dịch.

Khi bạn gặp những chi tiết tương tự trong một số thiết kế chiến lược, bạn có thể ngay lập tức đưa ra một giải pháp hợp lý.

Chúng tôi sử dụng nền tảng FMZ Quant làm ví dụ để giải thích, thử nghiệm và thực hành.

Chiến lược Ngôn ngữ lập trình chúng tôi sẽ sử dụng JavaScript

Đối với mục tiêu giao dịch, chúng tôi lấy thị trường tài sản blockchain (BTC, ETH, vv) làm đối tượng của chúng tôi

Thu thập và xử lý dữ liệu

Thông thường, tùy thuộc vào logic chiến lược, nó có thể sử dụng các giao diện khác nhau sau đây để lấy dữ liệu thị trường, hầu hết các logic chiến lược được điều khiển bởi dữ liệu thị trường (tất nhiên, một số chiến lược không quan tâm đến dữ liệu giá, chẳng hạn như chiến lược đầu tư cố định).

  • GetTicker: Nhận báo giá thời gian thực. Thông thường được sử dụng để nhanh chóng có được giá mới nhất hiện tại, Giá mua 1, Giá bán 1.

  • GetDepth: lấy độ sâu của sổ lệnh. Thông thường được sử dụng để lấy giá của từng lớp của độ sâu sổ lệnh và kích thước của các lệnh đang chờ.

  • GetTrade: Nhận hồ sơ giao dịch mới nhất của thị trường. Thông thường được sử dụng để phân tích hành vi thị trường trong một chu kỳ thời gian ngắn và phân tích những thay đổi vi mô trên thị trường.

  • GetRecords: Nhận dữ liệu đường K thị trường. Thông thường được sử dụng cho các chiến lược theo dõi xu hướng và tính toán các chỉ số.

Độ dung nạp lỗi

Khi thiết kế chiến lược, người mới bắt đầu thường bỏ qua các lỗi khác nhau và trực quan tin rằng kết quả của mỗi phần trong chiến lược được thiết lập.

Ví dụ, một số giao diện thị trường trả về dữ liệu chưa được thực hiện:

var depth = exchange.GetDepth()

// depth.Asks[0].Price < depth.Bids[0].Price "Selling 1" price is lower than "buying 1" price, this situation cannot exist on the market.
// Because the selling price is lower than the buying price, the order must have been executed.
// depth.Bids[n].Amount = 0 Order book buying list "nth" layer, order quantity is 0
// depth.Asks[m].Price = 0 Order book selling list "mth" layer, the order price is 0

Hoặc trực tiếp exchange.GetDepth() trả về một giá trị null.

Có rất nhiều tình huống kỳ lạ như vậy. Do đó, cần phải đối phó với những vấn đề có thể dự đoán được.

Cách thông thường để xử lý lỗi là loại bỏ dữ liệu và lấy lại nó.

Ví dụ:

function main () {
     while (true) {
         onTick()
         Sleep(500)
     }
}

function GetTicker () {
     while (true) {
         var ticker = exchange.GetTicker()
         if (ticker.Sell > ticker.Buy) { // Take the example of fault-tolerant processing that detects whether the "Selling 1" price is less than the "Buying 1" price.
                                               // Exclude this error, the current function returns "ticker".
             Return ticker
         }
         Sleep(500)
     }
}

function onTick () {
     var ticker = GetTicker() // Make sure the "ticker" you get doesn't exist the situation that "Selling 1" price is less than the "Buying 1" price.
     // ... specific strategy logic
}

Cách tiếp cận tương tự có thể được sử dụng cho các quy trình chịu lỗi khác có thể dự đoán.

Nguyên tắc thiết kế là bạn không bao giờ có thể sử dụng logic sai để điều khiển logic chiến lược.

Sử dụng dữ liệu đường K

Lấy dữ liệu đường K, gọi:

var r = exchange.GetRecords()

Dữ liệu đường K thu được là một mảng, như thế này:

[
    {"Time":1562068800000,"Open":10000.7,"High":10208.9,"Low":9942.4,"Close":10058.8,"Volume":6281.887000000001},
    {"Time":1562072400000,"Open":10058.6,"High":10154.4,"Low":9914.5,"Close":9990.7,"Volume":4322.099},
    ...
    {"Time":1562079600000,"Open":10535.1,"High":10654.6,"Low":10383.6,"Close":10630.7,"Volume":5163.484000000004}
]

Bạn có thể thấy rằng mỗi vòng cong {} chứa thời gian, giá mở cửa, giá cao nhất, giá thấp nhất, giá đóng cửa và khối lượng.

Đây là một thanh đường K. Dữ liệu đường K chung được sử dụng để tính toán các chỉ số như đường trung bình động, MACD v.v.

Dữ liệu đường K được truyền như một thông số (dữ liệu nguyên liệu), và sau đó các thông số chỉ số được thiết lập để tính toán chức năng của dữ liệu chỉ số, mà chúng tôi gọi là chức năng chỉ số.

Có rất nhiều chức năng chỉ số trên nền tảng giao dịch định lượng FMZ Quant.

Ví dụ, chúng tôi tính toán chỉ số trung bình động. Theo chu kỳ của dữ liệu đường K được thông qua, chúng tôi tính toán trung bình động của chu kỳ tương ứng.

Ví dụ, dữ liệu đường K vượt qua (một thanh đường K đại diện cho một ngày), tính toán đường trung bình hàng ngày, điều tương tự, nếu dữ liệu đường K của hàm chỉ số đường trung bình vượt qua là chu kỳ 1 giờ, thì chỉ số được tính toán là đường trung bình động 1 giờ.

Nếu tôi muốn tính toán chỉ số trung bình động 5 ngày, thì trước tiên chúng tôi chuẩn bị dữ liệu đường K hàng ngày:

var r = exchange.GetRecords(PERIOD_D1) // Pass parameters to the "GetRecords" function "PERIOD_D1" specifies the day K line to be acquired.
                                       // Specific function using method can be seen at: https://www.fmz.com/api#GetRecords

Nếu chúng ta muốn tính trung bình động 5 ngày, thì chúng ta phải đặt tham số chỉ số của hàm chỉ số là 5.

var ma = TA.MA(r, 5) // "TA.MA()" is the indicator function used to calculate the moving average indicator. The first parameter sets the daily K-line data r just obtained.
                             // The second parameter is set to 5. The calculated 5-day moving average is the same as the other indicators.

Chúng ta đã bỏ qua một vấn đề tiềm ẩn. nếu số lượng thanh đường K trong dữ liệu đường K nhỏ hơn 5, chúng ta có thể làm gì để tính toán một trung bình động 5 ngày hợp lệ?

Câu trả lời là không có gì anh có thể làm.

Bởi vì chỉ số trung bình động là mức trung bình của giá đóng của một số thanh K-line nhất định.

img

Do đó, trước khi sử dụng dữ liệu đường K và hàm chỉ số để tính toán dữ liệu chỉ số, cần xác định xem số thanh đường K trong dữ liệu đường K có đáp ứng các điều kiện cho việc tính toán chỉ số (các tham số chỉ số) hay không.

Vì vậy, trước khi tính toán trung bình động 5 ngày, bạn phải kiểm tra nó trước.

function CalcMA () {
     var r = _C(exchange.GetRecords, PERIOD_D1) // _C() is a fault-tolerant function, the purpose is to avoid r being null, you can get more information at: https://www.fmz.com/api#_C
     if (r.length > 5) {
         Return TA.MA(r, 5) // Calculate the moving average data with the moving average indicator function "TA.MA", return it as a function return value.
     }

     Return false
}

function main () {
     var ma = CalcMA()
     Log(ma)
}

img

Hiển thị kiểm tra ngược:

[null,null,null,null,4228.7,4402.9400000000005, ... ]

Bạn có thể thấy chỉ số trung bình di chuyển 5 ngày được tính toán. Bốn số đầu tiên là không, bởi vì số thanh K-line nhỏ hơn 5, và trung bình không thể được tính toán. Khi bạn đạt đến thanh K-line thứ 5, bạn có thể tính toán nó.

Mẹo để đánh giá các bản cập nhật K-line

Khi chúng ta viết chiến lược, thường có một kịch bản như vậy, chẳng hạn như chiến lược cần xử lý một số hoạt động khi mỗi chu kỳ K-line được hoàn thành, hoặc in một số nhật ký.

Làm thế nào chúng ta thực hiện các chức năng như vậy? Đối với người mới bắt đầu không có kinh nghiệm lập trình, nó có thể là một vấn đề khó khăn.

Làm thế nào để đánh giá chu kỳ thanh K-line đã hoàn thành. Chúng ta có thể bắt đầu với thuộc tính thời gian trong dữ liệu K-line. Mỗi lần chúng ta nhận được dữ liệu K-line, chúng ta sẽ đánh giá thuộc tính thời gian của thanh K-line cuối cùng của dữ liệu K-line này thay đổi hay không. Nếu nó được thay đổi, có nghĩa là có một thanh K-line mới được tạo ra (chứng minh rằng chu kỳ thanh K-line trước của thanh K-line mới được tạo ra đã hoàn thành), nếu không có thay đổi, có nghĩa là không có thanh K-line mới được tạo ra (chu kỳ thanh K-line cuối cùng hiện tại chưa hoàn thành).

Vì vậy, chúng ta cần một biến để ghi lại thời gian của thanh K-line cuối cùng của dữ liệu K-line.

var r = exchange.GetRecords()
var lastTime = r[r.length - 1].Time // "lastTime" used to record the last K-line bar time.

Trong thực tế, điều này thường xảy ra:

function main () {
     var lastTime = 0
     while (true) {
         var r = _C(exchange.GetRecords)
         if (r[r.length - 1].Time != lastTime) {
             Log ("New K-line bar generated")
             lastTime = r[r.length - 1].Time // Be sure to update "lastTime", this is crucial.

             // ... other processing logic
             // ...
         }

         Sleep(500)
     }
}

img

Bạn có thể thấy rằng trong backtest, chu kỳ đường K được thiết lập cho hàng ngày (các thông số không được chỉ định khiexchange.GetRecordskhi gọi function, và chu kỳ đường K được đặt theo backtest là tham số mặc định). Bất cứ khi nào thanh đường K mới xuất hiện, nó in một nhật ký.

Tính toán giá trị số

  • Tính toán thời gian truy cập giao diện trao đổi

Nếu bạn muốn có một màn hình hoặc kiểm soát nhất định về thời gian cần thiết cho chiến lược để truy cập giao diện trao đổi, bạn có thể sử dụng mã sau:

function main () {
     while (true) {
         var beginTime = new Date().getTime()
         var ticker = exchange.GetTicker()
         var endTime = new Date().getTime()

         LogStatus(_D(), "GetTicker() function time-consuming:", endTime - beginTime, "millisecond")
         Sleep(1000)
     }
}

Nói một cách đơn giản, dấu thời gian ghi sau khi gọiGetTickerchức năng được trừ đi từ dấu thời gian trước khi cuộc gọi, và số lượng milliseconds trải qua được tính toán, đó là thời gian mất bởiGetTickerchức năng từ thực thi để trở lại.

  • Sử dụng Math.min / Math.max để giới hạn giới hạn trên và dưới của giá trị

Ví dụ, trong quá trình đặt lệnh bán, số tiền của lệnh bán không được lớn hơn số tiền xu trong tài khoản. Bởi vì nếu nó lớn hơn số lượng tiền xu có sẵn trong tài khoản, thứ tự sẽ gây ra lỗi.

Chúng ta điều khiển nó như thế này:

Ví dụ, chúng tôi có kế hoạch bán ngắn 0.2 đồng xu.

var planAmount = 0.2
var account = _C(exchange.GetAccount)
var amount = Math.min(account.Stocks, planAmount)

Điều này đảm bảo rằng số lượng đơn đặt hàng sẽ không vượt quá số lượng coin có sẵn trong tài khoản.

Vì lý do tương tự,Math.maxđược sử dụng để đảm bảo giới hạn dưới của một giá trị.

  • Điều này thường áp dụng cho cảnh nào?

Nói chung, giao dịch thông thường có giới hạn đặt hàng gửi tối thiểu cho một số cặp giao dịch nhất định. Nếu nó thấp hơn số tiền tối thiểu, lệnh sẽ bị từ chối. Điều này cũng sẽ gây ra sự thất bại của chương trình.

Giả sử rằng BTC thường có số lượng đơn đặt hàng tối thiểu là 0,01.

Chiến lược giao dịch đôi khi có thể dẫn đến ít hơn 0,01 số lượng lệnh, vì vậy chúng ta có thể sử dụngMath.maxđể đảm bảo số lượng đặt hàng tối thiểu.

  • Số lượng đặt hàng, kiểm soát chính xác giá

Độ chính xác có thể được kiểm soát bằng cách sử dụng_N()chức năng hoặcSetPrecision function.

CácSetPrecision()chức năng chỉ cần thiết lập một lần, và số lượng vị trí thập phân trong số lượng đơn đặt hàng và giá trị giá được tự động cắt giảm trong hệ thống.

Các_N()chức năng là thực hiện cắt giảm điểm thập phân (kiểm soát chính xác) cho một giá trị nhất định.

Ví dụ:

var pi = _N(3.141592653, 2)
Log(pi)

Giá trị của pi được cắt giảm bằng dấu số thập phân, và 2 dấu số thập phân được dành riêng, đó là: 3.14

Xem tài liệu API để biết chi tiết.

Một số cài đặt logic

  • Thời gian, thực hiện một số hoạt động trong một khoảng thời gian nhất định

Bạn có thể sử dụng một cơ chế như vậy để sử dụng phương pháp phát hiện dấu thời gian để xác định dấu thời gian hiện tại trừ dấu thời gian của lần cuối cùng nhiệm vụ đã được thực hiện và tính toán thời gian trôi qua trong thời gian thực. Khi thời gian trôi qua vượt quá một khoảng thời gian nhất định. Sau đó, một hoạt động mới được thực hiện.

Ví dụ, được sử dụng trong một chiến lược đầu tư cố định.

var lastActTime = 0
var waitTime = 1000 * 60 * 60 * 12 // number of milliseconds a day
function main () {
     while (true) {
         var nowTime = new Date().getTime()
         if (nowTime - lastActTime > waitTime) {
             Log ("Execution Fixed")
             // ... specific fixed investment operation, buying operation.


             lastActTime = nowTime
         }

         Sleep(500)
     }
}

Đây là một ví dụ đơn giản.

  • Thiết kế một cơ chế khôi phục tự động cho chiến lược

Sử dụng FMZ Quant_G()chức năng, và thoát khỏi chức năng lưu, nó là thuận tiện để thiết kế một chiến lược để thoát khỏi quá trình lưu và khởi động lại trạng thái khôi phục tự động.

var hold = {
     Price : 0,
     Amount : 0,
}

function main () {
     if (_G("hold")) {
         var ret = _G("hold")
         hold.price = ret.price
         hold.amount = ret.amount
         Log("restore hold:", hold)
     }

     var count = 1
     while (true) {
         // ... strategy logic
         // ... In the strategy operation, it is possible that when opening a position, then assign the position price of the open position to "hold.price", and the amount of open positions is assigned to "hold.amount" to record the position information.

         hold.price = count++ // simulate some values
         hold.amount = count/10 // Simulate some values

         Sleep(500)
     }
}

function onexit () { // Click the stop button on the robot to trigger the execution of this function. After the execution, the robot stops.
     _G("hold", hold)
     Log("save hold:", JSON.stringify(hold))
}

img

Có thể thấy rằng dữ liệu trongholdđối tượng được lưu mỗi khi robot được dừng lại. và mỗi khi dữ liệu được khởi động lại, dữ liệu được đọc và giá trị củaholdđược khôi phục trở lại trạng thái trước khi dừng.

Tất nhiên, trên đây là một ví dụ đơn giản. Nếu nó được sử dụng trong một chiến lược giao dịch thực tế, nó nên được thiết kế theo các dữ liệu chính cần phải được khôi phục trong chiến lược (thường là thông tin tài khoản, vị trí, giá trị lợi nhuận, hướng giao dịch v.v.).

Hơn nữa, bạn cũng có thể thiết lập một số điều kiện khác để khôi phục.

Đây là một số mẹo để phát triển một chiến lược giao dịch, và tôi hy vọng nó có thể giúp người mới bắt đầu!

Thực hành tập luyện là cách nhanh nhất để cải thiện bản thân! Tôi chúc tất cả các bạn may mắn.


Có liên quan

Thêm nữa