[TOC] Bài hướng dẫn này chứa kiến thức cơ bản về viết chiến lược, bao gồm giới thiệu API, backtest, biểu đồ và hơn thế nữa. Sau khi học bài hướng dẫn cơ bản này, người dùng sẽ có thể sử dụng API cơ bản một cách thành thạo và viết một chiến lược bot ổn định. Trước khi học bài hướng dẫn, bạn cần phải học cách sử dụngBắt đầu FMZ Quant Platform.
Bài hướng dẫn phiên bản cũ:FMZ Quant (FMZ.COM) Hướng dẫn viết chiến lược 2.0 (Hướng dẫn); có rất nhiều chỉ mục bài viết trong hướng dẫn, được khuyến cáo đọc.
Giao dịch chương trình là sử dụng các chương trình để kết nối với các nền tảng thông qua API để đạt được việc mua và bán tự động hoặc các chức năng khác theo ý định thiết kế.
Hiện tại, có hai giao thức giao diện chính cho các nền tảng tiền điện tử: REST và Websocket. Mỗi lần giao thức REST thu thập dữ liệu, nó cần được truy cập một lần. Hãy lấy API của nền tảng mô phỏng
{"data:{"buy":"11351.73","high":"11595.77","last":"11351.85","low":"11118.45","open":"11358.74","quoteVol":"95995607137.00903936","sell":"11356.02","time":1565593489318,"vol":"3552.5153"}}
Bằng cách này, bạn có thể thấy rằng giao dịch sau báo giá thị trường mới nhất của cặp giao dịch BTC_USDT, sẽ thay đổi mỗi khi nó được làm mới;
Nền tảng giao dịch FMZ Quant bao gồm giao diện REST của mọi nền tảng, và sử dụng một cách thống nhất để gọi và định dạng dữ liệu thống nhất, làm cho việc viết chiến lược đơn giản hơn và chung hơn.
Hầu hết các phần của tài liệu API nền tảng FMZ sử dụng JavaScript làm ví dụ, nhưng do việc đóng gói, hầu như không có sự khác biệt giữa các ngôn ngữ khác nhau, và bạn chỉ cần chú ý đến các vấn đề cú pháp.
Vì Python có các phiên bản khác nhau, nó có thể được chỉ định ở đầu chương trình, chẳng hạn như:#!Python2
và#!Python3
. Lưu ý rằng JavaScript gần đây đã nâng cấp cú pháp ES6 của nó, và những người quan tâm có thể tìm hiểu về nó. Các mã Python và Javascript với các chức năng tương tự được hiển thị dưới đây. Có thể thấy rằng chỉ có sự khác biệt cú pháp, vì vậy tài liệu API chỉ đưa ra ví dụ về Javascript, và hướng dẫn này cũng sẽ tính đến các trường hợp sử dụng đặc biệt của Python.
#python code
def main():
while True:
Log(exchange.GetAccount().Balance)
Sleep(2000)
#the corresponding Js code
function main(){
while(true){
Log(exchange.GetAccount().Balance)
Sleep(2000)
}
}
Nền tảng FMZ Quant cung cấp
Chương trình chiến lược giống như một chương trình bình thường, được thực hiện theo các lệnh mã. Phần đặc biệt là phải có hàm
Các chức năng khác với các hành động đặc biệt được hiển thị như sau:
function onTick(){
var ticker = exchange.GetTicker()
var account = exchange.GetAccount()
//write the strategy logic here, and it will be called ever 6 seconds
}
function main(){
while(true){
onTick()
Sleep(6000)
}
}
Trong ví dụ trước đây, nếu có một lỗi trong truy cập mạng, chiến lược có thể dừng trực tiếp. Nếu bạn muốn một chiến lược tương tự như khởi động lại tự động và sẽ không dừng lại, bạn có thể sử dụng vòng lặp chính chịu lỗi trong chiến lược bot (không sử dụng
function onTick(){
var ticker = exchange.GetTicker()
var account = exchange.GetAccount()
//write the strategy logic here, and it will be called ever 6 seconds
}
function main(){
try{
while(true){
onTick()
Sleep(6000)
}
}catch(err){
Log(err)
}
}
Khi gọi bất kỳ API liên quan đến nền tảng nào, bạn cần xác định nền tảng và cặp giao dịch. Nếu chỉ có một cặp giao dịch nền tảng được thêm vào khi tạo bot, hãy sử dụngexchange
Ví dụ, những gìexchange.GetTicker()
sẽ nhận được là ticker thị trường của cặp giao dịch này.
Nền tảng FMZ Quant hỗ trợ thêm nhiều đối tượng exchanges
mảng để đại diện cho họ, cụ thể làexchanges[0]
vàexchanges[1]
... và vân vân, theo thứ tự thêm khi bot được tạo ra.BTC_USDT
, tiền cũ
Trong trường hợp này, chúng ta có thể sử dụng SetCurrency để chuyển đổi các cặp giao dịch, nhưexchange.SetCurrency("BTC_USDT")
; sau đó, cặp giao dịch bị ràng buộcexchange
trở thànhBTC_USDT
, sẽ duy trì hiệu lực cho đến lần gọi tiếp theo để thay đổi cặp giao dịch.Lưu ý rằng backtest hỗ trợ chuyển đổi các cặp giao dịch gần đâyDưới đây là một ví dụ cụ thể:
var symbols = ["BTC_USDT", "LTC_USDT", "EOS_USDT", "ETH_USDT"]
var buyValue = 1000
function main(){
for(var i=0;i<symbols.length;i++){
exchange.SetCurrency(symbols[i])
var ticker = exchange.GetTicker()
var amount = _N(buyValue/ticker.Sell, 3)
exchange.Buy(ticker.Sell, amount)
Sleep(1000)
}
}
Như đã đề cập trong ví dụ trước, giao diện thị trường thường là giao diện công cộng, có thể truy cập bởi tất cả mọi người. Các giao diện thị trường phổ biến là: GetTicker, GetDepth, GetRecords và GetTrades. Giá cả thị trường là cơ sở cho chiến lược để đưa ra phán quyết giao dịch. Sau đó, tôi sẽ giới thiệu chúng từng cái một. Tốt hơn là tự thử chúng trong
Mỗi giao diện thường có mộtInfo
trường, đại diện cho chuỗi dữ liệu ban đầu được trả về bởi nền tảng, và có thể được sử dụng để bổ sung thông tin bổ sung. Nó cần phải được phân tích trước khi sử dụng. JavaScript sử dụngJSON.parse()
, trong khi Python sử dụng thư viện json.Time
trường chỉ ra thời gian của yêu cầu, có thể được sử dụng để đánh giá sự chậm trễ.
khi sử dụng bất kỳ API trong bot, truy cập có thể thất bại và trở lạinull
, và Python trả vềNone
. Tại thời điểm này, dữ liệu đang sử dụng sẽ báo cáo một lỗi và làm cho bot dừng lại, vì vậy dung nạp lỗi là rất quan trọng.
GetTicker có lẽ là giao diện được sử dụng phổ biến nhất. Bạn có thể tìm thấy giá cuối cùng được thực hiện, giá mua1 và giá bán1, và khối lượng giao dịch gần đây nhất. Trước khi đặt lệnh, giá được thực hiện có thể được xác định theo thông tin ticker. Ví dụ về bot trả về:{"Info:{}, "High":5226.69, "Low":5086.37,"Sell":5210.63, "Buy":5208.5, "Last":5208.51, "Volume":1703.1245, "OpenInterest":0, "Time":1554884195976}
.
function main() {
var ticker = exchange.GetTicker()
Log(ticker) //return ticker in the debugging tool, and you can see the specific result
Log('Last time executed price:',ticker.Last, 'Buy1 price:', ticker.Buy)
}
GetDepth để có được thông tin sâu về các lệnh đang chờ. Mặc dù GetTicker bao gồm giá mua 1 và bán 1, nếu bạn muốn truy vấn các lệnh đang chờ sâu hơn, bạn có thể sử dụng giao diện này, để kiểm tra lên và xuống 200 lệnh đang chờ. Giá sốc có thể được tính bằng cách sử dụng giao diện này. Dưới đây là kết quả trả về thực tế. Trong số đó,
{
"Info":null,
"Asks":[
{"Price":5866.38,"Amount":0.068644},
{"Price":5866.39,"Amount":0.263985},
......
]
"Bids":[
{"Price":5865.13,"Amount":0.001898},
{"Price":5865,"Amount":0.085575},
......
],
"Time":1530241857399
}
Ví dụ sử dụng GetDepth cho Ask & Bids:
function main() {
var depth = exchange.GetDepth()
Log('Buy 1 price:', depth.Bids[0].Price, 'Sell 1 price:', depth.Asks[0].Price)
}
GetRecords là một trong những giao diện được sử dụng phổ biến nhất, có thể trả về thông tin giá trong một khoảng thời gian dài tại một thời điểm, đó là cơ sở để tính toán các chỉ số khác nhau. Nếu thời gian đường K không được chỉ định, có nghĩa là sử dụng thời gian mặc định khi thêm một bot. Chiều dài của đường K không thể được chỉ định, và nó sẽ tiếp tục tăng theo thời gian. Số tối đa là 2000, và trong cuộc gọi đầu tiên số là khoảng 200 (các nền tảng khác nhau trả về số khác nhau).
exchange.SetMaxBarLen(Len)
có thể đặt số lượng K-line được mua lần đầu tiên (được hỗ trợ bởi một số nền tảng), và đặt số lượng tối đa của K-line.Ví dụ:exchange.SetMaxBarLen(500)
.
GetRecords có thể chỉ định các khoảng thời gian như PERIOD_M1: 1 phút, PERIOD_M5: 5 phút, PERIOD_M15: 15 phút, PERIOD_M30: 30 phút, PERIOD_H1: 1 giờ và PERIOD_D1: 1 ngày.exchange.GetRecords(PERIOD_M1)
. Sau khi nâng cấp docker mới nhất, nó sẽ hỗ trợ tùy chỉnh các khoảng thời gian, chỉ cần vượt qua số thứ hai của khoảng thời gian như một tham số.Lưu ý rằng cũng có những biến số chữ cái lớn nhưPERIOD_M1
trong hướng dẫn. Chúng là các biến toàn cầu mặc định của FMZ. Nếu bạn quan tâm, bạn có thể
Ví dụ về dữ liệu trả về:
[
{"Time":1526616000000,"Open":7995,"High":8067.65,"Low":7986.6,"Close":8027.22,"Volume":9444676.27669432},
{"Time":1526619600000,"Open":8019.03,"High":8049.99,"Low":7982.78,"Close":8027,"Volume":5354251.80804935},
{"Time":1526623200000,"Open":8027.01,"High":8036.41,"Low":7955.24,"Close":7955.39,"Volume":6659842.42025361},
......
]
Ví dụ về K-line lặp lại:
function main(){
var close = []
var records = exchange.GetRecords(PERIOD_H1)
Log('total bars: ', records.length)
for(var i=0;i<records.length;i++){
close.push(records[i].Close)
}
return close
}
GetTrades có được dữ liệu giao dịch trong một khoảng thời gian nhất định (không phải dữ liệu giao dịch của riêng bạn), không được hỗ trợ bởi một số nền tảng.
Các giao diện đó liên quan đến tài khoản, vì vậy chúng không thể được lấy trực tiếp. Để lấy chúng, bạn cần sử dụng API-KEY để đăng nhập. Sau khi xử lý nền tảng FMZ tự động thống nhất, bạn có thể sử dụng trực tiếp chúng.
GetAccount để có được thông tin tài khoản. Là một trong những giao diện được sử dụng phổ biến nhất, nó cần phải được gọi trước khi đặt đơn đặt hàng, để tránh không đủ số dư. Kết quả trả về giống như:{"Stocks":0.38594816,"FrozenStocks":0,"Balance":542.858308,"FrozenBalance":0,"Info":{}}
Trong đó BTC_USDT
,
Lưu ý rằng kết quả trả lại là kết quả của cặp giao dịch được chỉ định, và thông tin về các loại tiền tệ khác trong tài khoản giao dịch nằm trong trường
Một bot liên tục in tổng giá trị của cặp giao dịch hiện tại:
function main(){
while(true){
var ticker = exchange.GetTicker()
var account = exchange.GetAccount()
var price = ticker.Buy
var stocks = account.Stocks + account.FrozenStocks
var balance = account.Balance + account.FrozenBalance
var value = stocks*price + balance
Log('Account value is: ', value)
LogProfit(value)
Sleep(3000)//sleep 3000ms(3s), A loop must has a sleep, or the rate-limit of the exchange will be exceed
//when run in debug tool, add a break here
}
}
Các phương pháp gọi bao gồmexchange.Buy(Price, Amount)
vàexchange.Buy(Price, Amount, Msg)
, trong đó null
sẽ được trả lại nếu lệnh không thành công, được sử dụng để truy vấn trạng thái lệnh.
Nếu bạn muốn đặt lệnh mua ở giá thị trường, exchange.Buy(-1, 0.5)
; nếu cặp giao dịch làETH_BTC
Một số nền tảng không hỗ trợ lệnh thị trường, cũng không kiểm tra lại tương lai.
Một số nền tảng có các yêu cầu chính xác cho giá cả và số tiền có thể được điều khiển bằng chức năng chính xác_N()
Đối với giao dịch tương lai,
Một ví dụ về mua một khi đạt đến giá tương ứng:
function main(){
while(true){
var ticker = exchange.GetTicker()
var price = ticker.Sell
if(price >= 7000){
exchange.Buy(_N(price+5,2), 1, 'BTC-USDT')
break
}
Sleep(3000)//Sleep 3000ms
}
Log('done')
}
Lệnh bán. Các thông số giống như exchange.Sell(-1, 0.2)
, có nghĩa là bán 0.2ETH với giá thị trường.
Khi giao diện chung này gọi phương thứcexchange.GetOrder(OrderId)
, Type
và giá trị thực tế của lệnhStatus
FMZ sử dụng hằng số toàn cầu để đại diện cho các giá trị này.Status
giá trị của một đơn đặt hàng chưa hoàn thành là 0, tương đương vớiORDER_STATE_PENDING
. Tất cả các hằng số toàn cầu này có thể được xem trong tài liệu... Kết quả trả về:
{
"Id":125723661, //Order id
"Amount":0.01, //Order ammount
"Price":7000, //Order price
"DealAmount":0, //Executed amount
"AvgPrice":0, //executed average price
"Status":0, //0: not completely executed; 1: executed; 2: canceled
"Type":1,//Order type; 0: buy order; 1: sell order
"ContractType":"",//contract type, used in futures trading
"Info":{} //the platform returns the raw information
}
}
Một chiến lược để mua một số tiền cụ thể:
function main(){
while(true){
var amount = exchange.GetAccount().Stocks
var ticker = exchange.GetTicker()
var id = null
if(5-amount>0.01){
id = exchange.Buy(ticker.Sell, Math.min(5-amount,0.2))
}else{
Log('Job completed')
return //return the main function, bot will stop
}
Sleep(3000) //Sleep 3000ms
if(id){
var status = exchange.GetOrder(id).Status
if(status == 0){ //Here you can aslo use "status == ORDER_STATE_PENDING" to judge
exchange.CancelOrder(id)
}
}
}
}
GetOrder lấy danh sách tất cả các lệnh chưa hoàn thành của cặp giao dịch hiện tại. Nếu không có lệnh chưa hoàn thành, trả về một mảng trống. Kết quả cụ thể của danh sách lệnh, chẳng hạn như
Ví dụ về việc hủy tất cả các lệnh của cặp giao dịch hiện tại:
function CancelAll(){
var orders = exchange.GetOrders()
for(var i=0;i<orders.length;i++){
exchange.CancelOrder(orders[i].Id) // cancel order by orderID
}
}
function main(){
CancelAll()
while(true){
//do something
Sleep(10000)
}
}
Theo ID đơn đặt hàng, hủy đơn đặt hàng.exchange.CancelOrder(OrderId)
. Nếu hủy thành công, trả về
Đối với tiền điện tử, giao dịch tương lai khác với giao dịch tại chỗ. Các chức năng trên của giao dịch tại chỗ cũng áp dụng cho giao dịch tương lai, và giao dịch tương lai duy nhất có các chức năng riêng của nó. Trước khi tiến hành giao dịch chương trình giao dịch tương lai tiền điện tử, bạn nên quen thuộc với các hoạt động thủ công trên trang web và hiểu các khái niệm cơ bản, chẳng hạn như mở, đóng, chéo, cô lập, đòn bẩy, thu nhập và lỗ gần, thu nhập nổi, biên và các khái niệm khác, cũng như các công thức tính toán tương ứng. Các hướng dẫn tương ứng có thể được tìm thấy trên các nền tảng tương lai khác nhau, và bạn cần phải tự học chúng.
Hợp đồng vĩnh viễn tương tự như hợp đồng tương lai, nhưng sự khác biệt là không có khái niệm nắm giữ các vị trí dài và ngắn cùng một lúc.
Nếu nền tảng hỗ trợ cả hợp đồng tương lai và giao ngay, chẳng hạn như hợp đồng tương lai của OKEX và Huobi, bạn cần chọn
Bước đầu tiên trong giao dịch tương lai là thiết lập hợp đồng được giao dịch. lấy OKEX tương lai làm ví dụ, chọn một cặp giao dịch BTC khi tạo bot hoặc backtesting, và bạn cũng cần thiết lập hợp đồng hàng tuần, tuần sau hoặc hàng quý trong mã. Nếu nó không được thiết lập, nó sẽ nhắcinvalid contract type
. Khác với các cặp giao dịch tại chỗ, các hợp đồng tương lai thường sử dụng tiền tệ giao dịch như BTC như biên độ. Thêm BTC vào một cặp giao dịch thường đại diện cho một cặp giao dịch BTC_USD sử dụng BTC như biên độ. Nếu có hợp đồng tương lai với USDT như biên độ, cần phải tạo một bot để thêm cặp giao dịch BTC_USDT. Ví dụ, các hợp đồng vĩnh cửu như Binance OKEX Futures, với cả hợp đồng biên độ tiền điện tử và USDT.Sau khi thiết lập cặp giao dịch, bạn cũng phải thiết lập loại hợp đồng cụ thể, chẳng hạn như vĩnh viễn, hàng tuần, tuần sau, v.v. Sau khi thiết lập hợp đồng, bạn có thể thực hiện các hoạt động như nhận báo giá thị trường, mua và bán.
Binance, OKEX, HuobiDM, v.v. có cả hợp đồng ký quỹ tiền điện tử và hợp đồng ký quỹ USDT, cần phải phân biệt khi thêm bot và thiết lập hợp đồng. Các cài đặt cụ thể như sau:
//OKEX Futures
exchange.SetContractType("swap") // set to perpetual contract
exchange.SetContractType("this_week") // set to weekly contract
exchange.SetContractType("next_week") // set to next week contract
exchange.SetContractType("quarter") // set to quarterly contract
//HuobiDM
exchange.SetContractType("this_week") // set to weekly contract
exchange.SetContractType("next_week") // set to next week contract
exchange.SetContractType("quarter") // set to quarterly contract
exchange.SetContractType("swap") // set to perpetual contract
//Binance Futures
exchange.SetContractType("swap") // set to perpetual contract, and notice that crypto-margined and USDT-margined contracts are all in the perpetual contract
exchange.SetContractType("quarter") // set to quarterly contract
exchange.SetContractType("next_quarter") // set to next quarter contract
//BitMEX
exchange.SetContractType("XBTUSD") // set to perpetual contract
exchange.SetContractType("XBTM19") // the contract settled at a specific time; for more details, please log in BitMEX to check each contract code
//GateIO
exchange.SetContractType("swap") // set to perpetual contract, and do not set the default as swap perpetual contract
//Deribit
exchange.SetContractType("BTC-27APR18") // the contract settled at a specific time; for more details, please log in Deribit to check out
Để có được danh sách thông tin vị trí hiện tại, OKEX (OKCOIN) tương lai có thể vượt qua trong một tham số để chỉ định các loại hợp đồng để được thu được.[]
, nếu không có vị trí. Thông tin vị trí được trả về như sau. Có rất nhiều thông tin cụ thể, cần phải được phân tích kết hợp với cặp giao dịch.
Loại dữ liệu | Tên biến | Mô tả |
---|---|---|
đối tượng | Thông tin | cấu trúc thô mà nền tảng trả về |
số | Mức ký quỹ | kích thước đòn bẩy; OKCoin là 10 hoặc 20, và vị trí chéo của tương lai OK trả về 10 (định), cho API thô không hỗ trợ |
số | Số tiền | Số lượng vị trí; OKCoin chỉ số số lượng hợp đồng (tổng số trên 1) |
số | Số lượng đóng băng | Số lượng vị trí bị đóng băng |
số | Giá cả | Giá trung bình vị trí |
số | Lãi suất | biên đóng băng |
số | Lợi nhuận | tương lai hàng hóa: lợi nhuận và lỗ của vị trí đánh dấu thị trường; tiền điện tử: đơn vị tiền điện tử: BTC / LTC, đơn vị tương lai truyền thống: RMB (lưu ý:Trong trường hợp vị trí chéo của hợp đồng tương lai OKCoin, nó đề cập đến lợi nhuận và lỗ thực hiện, không phải lợi nhuận và lỗ của vị trí. Dưới vị trí cô lập, nó đề cập đến lợi nhuận và lỗ của vị trí.) |
const | Loại | PD_LONG là vị trí dài (CTP sử dụng |
chuỗi | ContractType | hàng hóa tương lai là mã hợp đồng, và cổ phiếu là |
function main(){
exchange.SetContractType("this_week");
var position = exchange.GetPosition();
if(position.length>0){ //especially pay attention to judging the length of position before call, or an error will occur
Log("Amount:", position[0].Amount, "FrozenAmount:", position[0].FrozenAmount, "Price:",
position[0].Price, "Profit:", position[0].Profit, "Type:", position[0].Type,"ContractType:", position[0].ContractType)
}
}
Trước hết, bạn cần thiết lập kích thước đòn bẩy; phương pháp gọi:exchange.SetMarginLevel(10)
, trong đó exchange.SetDirection(Direction)
, tương ứng với các vị trí mở và đóng.Không giống như hợp đồng tương lai, nếu một hợp đồng vĩnh viễn không giữ các khái niệm của dài và ngắn cùng một lúc, đó là một vị trí duy nhất không được phép. khi bạn hoạt động mở ngắn trên một vị trí dài, vị trí dài sẽ được tự động đóng, vì vậy bạn chỉ cần thiết lậpbuy
vàsell
Nếu nó hỗ trợ hai hướng vị trí, bạn cần phải thiết lậpclosebuy
, closesell
.Các mối quan hệ cụ thể:
Hoạt động | SetDirection Parameters | Chức năng đặt lệnh |
---|---|---|
Khả năng mở | exchange.SetDirection (( |
trao đổi.Buy ((() |
Đóng vị trí dài | exchange.SetDirection (( |
trao đổi.Bán. |
Khả năng mở ngắn | exchange.SetDirection (( |
trao đổi.Bán. |
Khóa vị trí ngắn | exchange.SetDirection (( |
trao đổi.Buy ((() |
Cuối cùng, có mã cụ thể cho các vị trí mở và đóng. Số lượng lệnh được đặt khác nhau từ nền tảng này sang nền tảng khác. Ví dụ, hợp đồng tương lai Huobi dựa trên số lượng hợp đồng, và một hợp đồng là 100 đô la Mỹ. Lưu ý rằng backtest tương lai không hỗ trợ lệnh thị trường.
function main(){
exchange.SetContractType("this_week") // for example, set OKEX futures to weekly contract
price = exchange.GetTicker().Last
exchange.SetMarginLevel(10) // set to 10 times of leverage
exchange.SetDirection("buy") // set the order type as buy long
exchange.Buy(price+10, 20) // set contract quantity as 20 orders
pos = exchange.GetPosition()
Log(pos)
Log(exchange.GetOrders()) // check out if there is any unfinished order
exchange.SetDirection("closebuy"); // if it is a perpetual contract, directly set exchange.SetDirection("sell")
exchange.Sell(price-10, 20)
}
Cho một ví dụ chiến lược cụ thể về các vị trí đóng cửa đầy đủ như sau:
function main(){
while(true){
var pos = exchange.GetPosition()
var ticker = exchange.GetTicekr()
if(!ticker){
Log('not able to obtain ticker')
return
}
if(!pos || pos.length == 0 ){
Log('no position')
return
}
for(var i=0;i<pos.length;i++){
if(pos[i].Type == PD_LONG){
exchange.SetContractType(pos[i].ContractType)
exchange.SetDirection('closebuy')
exchange.Sell(ticker.Buy, pos[i].Amount - pos[i].FrozenAmount)
}
if(pos[i].Type == PD_SHORT){
exchange.SetContractType(pos[i].ContractType)
exchange.SetDirection('closesell')
exchange.Buy(ticker.Sell, pos[i].Amount - pos[i].FrozenAmount)
}
}
var orders = exchange.Getorders()
Sleep(500)
for(var j=0;j<orders.length;j++){
if(orders[i].Status == ORDER_STATE_PENDING){
exchange.CancelOrder(orders[i].Id)
}
}
}
}
Giao dịch đòn bẩy tiền điện tử cần chuyển sang tài khoản đòn bẩy trong mã, và các phần khác giống như giao dịch tại chỗ.
Sử dụngexchange.IO("trade_margin") để chuyển sang chế độ tài khoản đòn bẩy; đặt lệnh và nhận tài sản tài khoản sẽ truy cập vào giao diện đòn bẩy của nền tảng. Sử dụngexchange.IO("trade_normal") để chuyển trở lại chế độ tài khoản thông thường.
Các nền tảng được hỗ trợ:
Giao dịch tương lai hàng hóa và giao dịch tương lai tiền điện tử khá khác nhau. Trước hết, thời gian giao dịch tương lai hàng hóa rất ngắn, nhưng tiền điện tử được giao dịch trong 24 giờ; giao thức tương lai hàng hóa không phải là một API REST thường được sử dụng; tần suất giao dịch và số lượng đơn đặt hàng đang chờ của tương lai hàng hóa bị giới hạn, nhưng của tiền điện tử rất lỏng lẻo, v.v. Do đó, có nhiều điểm cần chú ý đặc biệt khi giao dịch tương lai hàng hóa, và nó được khuyến cáo cho những người có kinh nghiệm phong phú trong các hoạt động thủ công. FMZ hiện hỗ trợ robot mô phỏng tương lai hàng hóa, và bạn có thể tham khảo:https://www.fmz.com/bbs-topic/325Để thêm các công ty tương lai hàng hóa:https://www.fmz.com/bbs-topic/371
Các hợp đồng tương lai hàng hóa đã thực hiện giám sát minh bạch vào tháng 6 năm 2019; đối với chương trình cá nhân, người dùng cá nhân cần phải mở tài khoản để nộp đơn xin mã ủy quyền cho các nhà môi giới tương lai (mẫu thông tin ứng dụng cụ thể có thể được gửi đến nhóm WeChat hoặc nhóm QQ), thường mất 4-5 ngày; các thủ tục khá phức tạp. Là một nhà cung cấp giao dịch theo chương trình, nền tảng FMZ đã nộp đơn xin mã ủy quyền phần mềm từ các nhà cung cấp dịch vụ tương lai khác nhau. Người dùng có thể sử dụng chúng trực tiếp mà không cần nộp đơn. Khi thêm một nhà môi giới tương lai Quant, hãy tìm kiếm
Do lợi thế của cấu trúc nền tảng FMZ Quant, người dùng cũng có thể thêm nhiều tài khoản môi giới tương lai và thực hiện một số chức năng mà các phần mềm giao dịch tương lai hàng hóa khác không thể hoàn thành, chẳng hạn như tổng hợp tick tần số cao; bạn có thể tham khảo:https://www.fmz.com/bbs-topic/1184
Trước hết, vì nó không phải là giao dịch 24h và đòi hỏi một hoạt động đăng nhập, cần phải đánh giá tình trạng liên kết trước khi giao dịch.exchange.IO("status")
làtrue
, mà inidcates kết nối thành công với nền tảng. Nếu API được gọi khi đăng nhập không thành công, _C(exchange.SetContractType,"MA888")
, mà sẽ đảm bảo một đăng nhập thành công.
Các mã mua bán và giao dịch giá thị trường của hợp đồng tương lai hàng hóa giống như hợp đồng tương lai tiền điện tử.
function main(){
_C(exchange.SetContractType,"MA888") //If you do not log in successfully, you cannot subscribe to the contract, so better to try again
while(true){
if(exchange.IO("status")){
var ticker = exchange.GetTicker()
Log("MA888 ticker:", ticker)
LogStatus(_D(), "Already connected with CTP !")//_D obtain event
} else {
LogStatus(_D(), "Not connected with CTP !")
Sleep(1000)
}
}
}
Bạn nên sử dụng thư viện tương lai hàng hóa để giao dịch (sẽ được mô tả sau), mã sẽ rất đơn giản vào thời điểm này và không cần phải xử lý các chi tiết tẻ nhạt.https://www.fmz.com/strategy/57029
function main() {
// Use the CTA strategy framework of commodity futures library
$.CTA(Symbols, function(st) {
var r = st.records
var mp = st.position.amount
var symbol = st.symbol
/*
"r" represents K-line, "mp" indicates the position amount of the current variety; positive number means long position, negative number means short position, and 0 means no position; "symbol" is the variety name
if the return value is n:
n = 0 : full close positions (no matter now they are long or short)
n > 0 : if right now long positions are held, add n long positions; if now they are short positions, close n short posiitons; if n is over the position amount right now, reverse to open long positions
n < 0 : if right now short positions are held, add n short positions; if now they are long positions, close n long posiitons; if -n is over the position amount right now, reverse to open short positions
*/
if (r.length < SlowPeriod) {
return
}
var cross = _Cross(TA.EMA(r, FastPeriod), TA.EMA(r, SlowPeriod));
if (mp <= 0 && cross > ConfirmPeriod) {
Log(symbol, "Golden Cross Period", cross, "the moment position", mp);
return Lots * (mp < 0 ? 2 : 1)
} else if (mp >= 0 && cross < -ConfirmPeriod) {
Log(symbol, "Death Cross Period", cross, "the moment position", mp);
return -Lots * (mp > 0 ? 2 : 1)
}
});
}
Tiền tương lai hàng hóa sử dụng giao thức CTP, và tất cả các báo giá thị trường và thực thi lệnh sẽ chỉ được thông báo sau khi có thay đổi, trong khi các truy vấn về lệnh, tài khoản và vị trí là các truy vấn hoạt động. Do đó, nó phù hợp để viết các chiến lược tần số cao dựa trên sự kiện.GetTicker
, GetDepth
vàGetRecords
, tất cả cần phải có dữ liệu được lưu trữ tạm để có được dữ liệu mới nhất. Nếu không có dữ liệu, nó sẽ chờ cho đến khi có dữ liệu, vì vậy không cần thiết cho chiến lược sử dụng
Nếu bạn muốn có được dữ liệu mỗi khi bạn nhận được báo giá thị trường, ngay cả khi nó là dữ liệu cũ, bạn có thể chuyển sang chế độ cập nhật ngay lập tức của báo giá thị trườngexchange.IO("mode", 0)
. Tại thời điểm này, chiến lược không thể được viết như một sự kiện điều khiển, và một sự kiện exchange.IO("mode", 1)
để chuyển trở lại chế độ cache mặc định.
Khi vận hành một hợp đồng duy nhất, sử dụng chế độ mặc định. Tuy nhiên, nếu có nhiều hợp đồng, có thể một trong các hợp đồng không cập nhật báo giá thị trường, dẫn đến việc chặn giao diện để có được báo giá thị trường, và các bản cập nhật báo giá của các hợp đồng khác cũng không thể có được. Để giải quyết vấn đề này, chế độ cập nhật ngay lập tức có thể được sử dụng, nhưng không thuận tiện để viết các chiến lược tần số cao.exchange.IO("wait")
Nếu nhiều đối tượng trao đổi được thêm vào, mà là hiếm trong tương lai hàng hóa, bạn có thể sử dụngexchange.IO("wait_any")
, và
Đẩy thay đổi thị trường:{Event:"tick", Index: platform index (in the order of the platforms added in the bot), Nano: event of nanosecond-level time, Symbol: contract name}
Đẩy lệnh:{Event:"order", Index:Exchange index, Nano:Event of nanosecond-level time, Order:Order information (same as GetOrder)}
Vào thời điểm này, cấu trúc chiến lược có thể được viết như sau:
function on_tick(symbol){
Log("symbol update")
exchange.SetContractType(symbol)
Log(exchange.GetTicker())
}
function on_order(order){
Log("order update", order)
}
function main(){
while(true){
if(exchange.IO("status")){ //Judge the link status
exchange.IO("mode", 0)
_C(exchange.SetContractType, "MA888")//Subscribe to MA; only the subscription request for the first time is ture, and the later ones are program switches, which do not consume time
_C(exchange.SetContractType, "rb888")//Subscribe to rb
while(true){
var e = exchange.IO("wait")
if(e){
if(e.event == "tick"){
on_tick(e.Symbol)
}else if(e.event == "order"){
on_order(e.Order)
}
}
}
}else{
Sleep(10*1000)
}
}
}
Cũng lưu ý sự khác biệt giữa hợp đồng tương lai hàng hóa và nền tảng tiền điện tử. Ví dụ,
exchange.IO("công cụ"): nó trả về danh sách tất cả các hợp đồng trên nền tảng {tên hợp đồng: chi tiết} dưới dạng từ điển, và chỉ hỗ trợ robot.exchange.IO("sản phẩm"): nó trả về danh sách tất cả các mặt hàng trên nền tảng {tên hợp đồng: chi tiết} dưới dạng từ điển và chỉ hỗ trợ bot.exchange.IO("đăng ký"): nó trả về các báo giá thị trường đã đăng ký trên nền tảng dưới dạng từ điển và chỉ hỗ trợ bot.
CácContractType
của tương lai CTP truyền thống đề cập đến ID hợp đồng, đó là nhạy cảm với chữ cái lớn.exchange.SetContractType("au1506")
. Sau khi hợp đồng được thiết lập thành công, nó sẽ trả về thông tin chi tiết của hợp đồng, chẳng hạn như số tiền mua tối thiểu, phí dịch vụ, thời gian giao hàng, v.v. Khi đăng ký nhiều hợp đồng, chỉ lần đầu tiên yêu cầu đăng ký thực sự được gửi, và sau đó cặp giao dịch chỉ được chuyển đổi ở mức mã, không mất thời gian. Hợp đồng liên tục chính là mã 888, chẳng hạn như MA888, hợp đồng tỷ lệ liên tục là 000, chẳng hạn như MA000; 888 và 000 là giao dịch hợp đồng ảo chỉ hỗ trợ backtest, và robot thực sự chỉ hỗ trợ báo giá thị trường.Tuy nhiên, Mylanguage có thể vận hành hợp đồng chính, và chương trình sẽ tự động thay đổi các vị trí, tức là đóng các vị trí không chính và mở các vị trí mới trên các vị trí chính.
Login không thành công không thể thiết lập hợp đồng, nhưng sẽ trở lại ngay lập tức, vì vậy bạn có thể thử bằng
SetDirection
có thể nhận được bốn thông số:buy, closebuy, sell, closesell
Các hợp đồng tương lai hàng hóa có nhiềuclosebuy_today
vàclosesell_today
, cho thấy đóng các vị trí hiện tại; mặc định làclosebuy/ closesell
, cho thấy đóng các vị trí ngày hôm qua; chỉ có các loại của Sàn giao dịch tương lai Thượng Hải được chia thành đóng ngày hôm nay và đóng ngày hôm qua, có thể ảnh hưởng đến phí dịch vụ, do đó, cần phải ưu tiên đóng các vị trí ngày hôm qua. Đối với tương lai truyền thống CTP, bạn có thể đặt tham số thứ hai là
Hoạt động | SetDirection Parameters | Chức năng đặt lệnh |
---|---|---|
Khả năng mở | exchange.SetDirection (( |
trao đổi.Buy ((() |
Đóng vị trí dài | exchange.SetDirection (( |
trao đổi.Bán. |
Khả năng mở ngắn | exchange.SetDirection (( |
trao đổi.Bán. |
Khóa vị trí ngắn | exchange.SetDirection (( |
trao đổi.Buy ((() |
Ví dụ sau đây là một chức năng vị trí đóng cụ thể. Lưu ý rằng ví dụ này quá đơn giản. Bạn cũng nên xem xét liệu nó có nằm trong thời gian giao dịch, làm thế nào để thử lại lệnh đang chờ nếu nó không được hoàn thành hoàn toàn, khối lượng lệnh tối đa là bao nhiêu, tần suất có quá cao và liệu đó là giá trượt hay giá thị trường v.v. Chỉ để tham khảo,nó là một gói thư viện của các nền tảng được đề xuất để mở và đóng các vị trí trong robot thực sự:https://www.fmz.com/strategy/12961Có một phần giới thiệu cụ thể trong phần thư viện, và cũng được khuyến cáo nghiên cứu mã nguồn của thư viện.
function Cover(contractType, amount, slide) {
for (var i = 0; i < positions.length; i++) {
if (positions[i].ContractType != contractType) {
continue;
}
var depth = _C(e.GetDepth);
if (positions[i].Type == PD_LONG || positions[i].Type == PD_LONG_YD) {
exchange.SetDirection(positions[i].Type == PD_LONG ? "closebuy_today" : "closebuy");
exchange.Sell(depth.Bids[0]-slide, amount, contractType, positions[i].Type == PD_LONG ? "Close today" : "Close yesterday", 'Bid', depth.Bids[0]);
} else {
exchange.SetDirection(positions[i].Type == PD_SHORT ? "closesell_today" : "closesell");
exchange.Buy(depth.Asks[0]+slide, amount, contractType, positions[i].Type == PD_SHORT ? "Close today" : "Close yesterday", 'Ask', depth.Asks[0]);
}
}
}
Hàng hóa tương lai hỗ trợ các loại lệnh tùy chỉnh (hỗ trợ cho robot, nhưng không phải cho backtest), được chỉ định bằng hậu tố, được thêm vào
exchange.SetDirection("buy_ioc");
exchange.SetDirection("sell_gtd-20170111")
Các hậu tố cụ thể:
Theo mặc định, các giao diện mở trong các nhà môi giới tương lai hàng hóa đều là giao diện CTP. Nếu cần thiết, chúng có thể được thay thế bằng giao diện Esunny. Thông qua việc đóng gói FMZ, phương pháp triệu hồi giống nhau. Sự khác biệt là tài khoản, lệnh và vị trí đều ở chế độ đẩy, vì vậy docker sẽ duy trì dữ liệu này tại địa phương và sẽ quay lại ngay lập tức khi giao diện tương ứng được gọi, mà không thực sự thực hiện yêu cầu.
Các loại đơn đặt hàng tùy chỉnh là:
Khi đăng một bản ghi nhật ký trên giao diện bot, và thêm ký tự Log('Push to WeChat@')
.
Màu log cũng có thể được tùy chỉnh, chẳng hạn nhưLog('this is a log in red font #ff0000')
.
#ff0000
là con số mười sáu của màu RGB, cho thấy tất cả các tệp nhật ký được lưu trữ trong cơ sở dữ liệu SqLit của bot trong thư mục nơi docker nằm, có thể được tải xuống và mở bằng phần mềm cơ sở dữ liệu, hoặc có thể được sử dụng để sao chép sao lưu và khôi phục (tên cơ sở dữ liệu và ID bot là giống nhau).
Nó ghi lại lợi nhuận, và vẽ đường cong lợi nhuận trên giao diện bot, có thể được giữ lại sau khi bot được khởi động lại.LogProfit(1000)
Lưu ý rằng tham số củaLogProfit
không nhất thiết là lợi nhuận, và nó có thể là bất kỳ số và cần phải được điền vào bởi chính mình.
Nếu trạng thái bot, vì nhật ký sẽ được lưu trước và cập nhật liên tục, cần thông tin chỉ để hiển thị không để lưu, bạn có thể sử dụngLogStatus
Các tham số củaLogStatus
là chuỗi, mà cũng có thể được sử dụng để đại diện cho thông tin bảng.
Một ví dụ về bảng hiển thị vị trí bot thực cụ thể:
var table = {type: 'table', title: 'position information', cols: ['Column1', 'Column2'], rows: [ ['abc', 'def'], ['ABC', 'support color #ff0000']]};
LogStatus('`' + JSON.stringify(table) + '`'); // After serialization, JSON will be added the character "'" on both sides, which is regarded as a comlpex messag format (now supporting tables)
LogStatus('The first line information\n`' + JSON.stringify(table) + '`\nthe third line information'); // the table information can be displayed in multiple lines
LogStatus('`' + JSON.stringify([table, table]) + '`'); // Multiple tables are supported to be displayed at the same time, which will be displayed in one group by TAB
LogStatus('`' + JSON.stringify(tab1) + '`\n' + '`' + JSON.stringify(tab2) + '`\n'); // Multiple tables are displayed up and down by arrangement
Parameter của nó là số millisecond, chẳng hạn như:Sleep(1000)
Do tần số truy cập hạn chế của tất cả các nền tảng, thời gian ngủ nên được thêm vào vòng lặp vô hạn trong các chiến lược chung.
Sau khi bot khởi động lại, chương trình sẽ khởi động lại._G
là rất thuận tiện và thực tế, và nó có thể lưu các nội dung JSON nối tiếp._G
hàm được viết bằngonexit()
, để mỗi khi chiến lược được dừng lại, thông tin cần thiết sẽ được lưu tự động.
Nếu bạn muốn lưu nhiều dữ liệu định dạng hơn, chức năng _G không phù hợp, nhưng