[TOC]
Tutorial ini akan merangkumi lebih banyak butiran mengenai platform FMZ, lebih banyak kemahiran praktikal tentang menggunakan API.
Selepas mempelajari keseluruhan tutorial, anda akan menggunakan sepenuhnya FMZ dan dapat menulis strategi yang lebih disesuaikan, lebih cekap dan lebih kompleks.
Anda boleh berdagang di pelbagai bursa dan pelbagai simbol dalam satu robot dengan mudah.
exchange.GetTicker()
apabila satu pertukaran ditambahexchanges[0].GetTicker()
, exchanges[1].GetTicker()
exchange
dengan menggunakanIO
fungsivar symbols = ["BTC_USDT", "LTC_USDT", "EOS_USDT", "ETH_USDT", "BCC_USDT"]
var buyValue = 1000
function main(){
for(var i=0;i<symbols.length;i++){
exchange.IO("currency", symbols[i]) // It is always valid until the next change
var ticker = exchange.GetTicker()
var amount = _N(buyValue/ticker.Sell, 3)
exchange.Buy(ticker.Sell, amount)
Sleep(1000)
}
}
Setakat ini, FMZ menyokong semua bursa niaga hadapan utama, seperti OKEX, HuobiDM, BitMEX, GateIO dan Deribit, dan kontrak swap mereka.
Untuk berdagang niaga hadapan di FMZ, anda perlu menambah pertukaran niaga hadapan terlebih dahulu, menetapkan simbol apabila memulakan bot dan menetapkan jenis kontrak dalam kod anda.
Jika bursa menyokong kedua-dua spot dan niaga hadapan, mereka harus ditambahkan kepada FMZ secara berasingan.
Gambar di bawah menunjukkan cara menetapkan simbol niaga hadapan ke BTC apabila memulakan bot.
Di bawah adalah bagaimana untuk menetapkan jenis kontrak untuk setiap pertukaran.
exchange.SetContractType("swap")
exchange.SetContractType("this_week")
exchange.SetContractType("next_week")
exchange.SetContractType("quarter")
exchange.SetContractType("this_week")
exchange.SetContractType("next_week")
exchange.SetContractType("quarter")
exchange.SetContractType("XBTUSD")
exchange.SetContractType("XBTM19")
exchange.SetContractType("swap")
exchange.SetContractType("BTC-PERPETUAL")
exchange.SetContractType("BTC-27APR18")
Pengenalan asas
FMZ mempunyai dua mod backtesting:real tick
dansimulate tick
. Tahap tik sebenar mengandungi semua data sejarah yang telah selesai (satu tik setiap saat), jadi hasil backtesting lebih boleh dipercayai. Tahap simulasi menggunakan data klines sejarah pada selang yang digunakan oleh strategi anda. Tik dalam satu kline dihasilkan oleh algoritma yang sama dengan MT4, anda boleh mencari maklumat lanjut dihttps://www.mql5.com/en/articles/75Sementara itu, selang yang lebih pendek boleh dipilih sebagai pangkalan-klines untuk menjana kutu.
Mod tik simulasi jauh lebih cepat tetapi kurang tepat daripada mod tik sebenar. Julat kline yang lebih pendek dalam mod tik simulasi adalah kompromi antara ketepatan dan kelajuan ujian.
Konfigurasi Backtest
Berikut adalah tetapan lalai:Titik tersembunyi:
Hasil ujian belakang
Apabila memanggil mana-mana fungsi yang mengakses API pertukaran (sepertiGetTicker
, Buy
, CancelOrder
, dan lain-lain...), anda mungkin mendapat kegagalan akses kerana masalah pelayan pertukaran, parameter yang salah, masalah penghantaran rangkaian, dan sebagainya.null
Jadi anda perlu tahu bagaimana untuk menangani kesilapan.
Apa yang salah?
Bot akan mengembalikan mesej ralat apabila ralat berlaku. Hanya mencari nama pertukaran + msg ralat, anda boleh mencari apa masalahnya. Sebagai contoh,{"result":false,"error_code":20049}
dikembalikan apabila panggilanexchange.GetAccount()
di OKEX.OKEX 20049
Inilah hasilnya:Anda juga boleh menyemak kod ralat pada pertukaran API doc, sepertiKod ralat OKEX Untuk niaga hadapan
Kesalahan urus niaga
Anda harus mempertimbangkan bagaimana untuk menangani kesilapan apabila menulis kod strategi.
// 1.Deal when the result is null
var ticker = exchange.GetTicker()
while(ticker == null){
Log('GetTicker error')
Sleep(100)
ticker = exchange.GetTicker()
}
Log(ticker.Last);
// 2.Refer when the result is not null
var ticker = exchange.GetTicker()
if(!ticker){
Log(ticker.Last)
}
// 3._C() fucntion retry
var ticker = _C(exchange.GetTicker) // can't apply _C to CancelOrder, Why?
Log(ticker.Last)
// 4. try catch
try{
var ticker = exchange.GetTicker()
Log(ticker.Last)
}
catch(err){
Log('GetTicker error: ', err)
Log(GetLastError()) //literal means, get last error
}
FMZ membungkus semua data pertukaran yang berbeza ke dalam format yang sama, yang memudahkan untuk menulis strategi rentas platform. Walau bagaimanapun, anda tidak dapat mendapatkan data khusus API tertentu yang memberikan maklumat tambahan dan tidak dapat mengakses API yang tidak disokong FMZ. Terdapat dua penyelesaian untuk masalah ini.
GetRawJSON
Kembalikan kandungan asal (string) yang dikembalikan oleh permintaan API REST terakhir, yang boleh digunakan untuk menganalisis maklumat mentah sendiri.
function main(){
var account = exchange.GetAccount() //the account doesn't contain all data returned by the request
var raw = JSON.parse(exchange.GetRawJSON())//raw data returned by GetAccount()
Log(raw)
}
HttpQuery
Cari semua butiran tentangHttpQuery
padahttps://fmz-docs.readthedocs.io/en/latest/code_Instruction/Global Function.html#
HttpQuery
mengembalikan data mentah permintaan ini yang harus dianalisis terlebih dahulu.
//FMZ doesn't have a standard function for exchangeInfo that return the trading-information about all symbols.
var exchangeInfo = JSON.parse(HttpQuery('https://api.binance.com/api/v1/exchangeInfo'))
Log(exchangeInfo) // FMZ doesn't have a standard function for this API
var ticker = JSON.parse(HttpQuery('https://api.binance.com/api/v1/ticker/24hr'))
Log(ticker)
Untuk API awam,HttpQuery
adalah fungsi yang sangat berguna.HttpQuery
hanya menyokong JavaScript, untuk Python, menggunakanurlib2
ataurequest
perpustakaan untuk menghantar permintaan http secara langsung.
IO
Untuk API peribadi, menggunakanHttpQuery
akan menjadi sangat rumit kerana anda perlu berurusan dengan API-kunci, tanda, hash, dllIO
adalah fungsi berguna untuk keadaan ini, semak padahttps://fmz-docs.readthedocs.io/en/latest/code_Instruction/Extent API.html#io. IO
Pada bahagian ini, kami hanya memberi tumpuan kepada akses kepada API peribadi.
Menggunakan fungsi ini memerlukan pemahaman API asal bursa terlebih dahulu. Di bawah adalah langkah untuk membuat pesanan berhenti yang tidak disokong oleh FMZ di BitMEX.
POST
, Parameter termasuk simbol,sisi, orderQty,stopPx,ordType,yang harus disusun seperti "simbol=XBTUSD&side=Buy&orderQty=1&stopPx=4000&ordType=StopKod JavaScript akhir:
var id = exchange.IO("api", "POST", "/api/v1/order", "symbol=XBTUSD&side=Buy&orderQty=1&stopPx=4000&ordType=Stop")
Pada asasnya semua pertukaran mata wang digital menyokong menghantar data pasaran melalui websocket, dan beberapa pertukaran bahkan menyokong mengemas kini maklumat akaun. Berbanding dengan API selebihnya, websocket umumnya mempunyai kelebihan latensi rendah, frekuensi tinggi, dan tidak terhad oleh frekuensi permintaan API platform. Kelemahannya adalah bahawa ia mungkin terganggu dan pemprosesannya tidak intuitif.
Untuk JavaScript, anda boleh menggunakanDial
fungsi untuk menyambung ke websocket, Untuk Python, anda boleh menggunakanDial
atauwebsocket_client
libray.
Tutorial ini akan memberi tumpuan kepada menyambungkan websocket menggunakan JavaScript danDial
fungsi di FMZ Quantization Platform. Untuk memperluaskan pelbagai kegunaan, fungsi Dial telah dikemas kini beberapa kali. Tutorial ini akan menunjukkan strategi yang didorong oleh peristiwa berasaskan websocket dan cara menyambung ke pelbagai pertukaran.
Disambungkan ke websocket
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
compress
bermaksud bahawa data adalah dalam format mampat, dan parametermode
mewakili sama ada penghantaran atau penerimaan dimampatkan. Contoh menyambung ke OKEXvar client = Dial("wss://real.okex.com:10441/websocket?compress=true|compress=gzip_raw&mode=recv")
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr?reconnect=true")
var client = Dial("wss://ws-feed.pro.coinbase.com", 60)
client.write('{"type": "subscribe","product_ids": ["BTC-USD"],"channels": ["ticker","heartbeat"]}')
Menerima data
Secara amnya, data dari websocket boleh dibaca secara berterusan tanpa tidur dalam gelung tanpa akhir.
function main() {
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
while (true) {
var msg = client.read() //receve data from client
var data = JSON.parse(msg) //change raw string to js object
// do something, don't need sleep.
}
}
Websocket mendorong data dengan sangat cepat. yang mendasari docker cache semua data dalam antrian, dan kemudian mengembalikan yang pertama apabila program memanggilread
. Operasi rangkaian robot sepertiBuy
,GetAccount
,CancelOrder
untuk maklumat seperti dorongan transaksi, dorongan akaun, dorongan mendalam subset, dll, kita memerlukan data sejarah. untuk data pasaran, kita biasanya hanya peduli dengan yang terbaru.
Peraturanread()
fungsi mengembalikan data tertua dalam barisan jika tidak ada argumen, dan blok apabila tidak ada data (program dihentikan di sini).read(-2)
untuk segera mengembalikan data terkini, dan kembalinull
jika tiada data dalam barisan (program tidak akan berhenti).
Sambungkan ke pelbagai websocket
Dalam kes ini adalah jelas bahawa program tidak boleh menggunakan mudahread()
kerana pertukaran akan menyekat dan menunggu data baru, dan pertukaran lain tidak akan menerima data baru sendiri dengan segera.
function main() {
var binance = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
var coinbase = Dial("wss://ws-feed.pro.coinbase.com")
coinbase.write('{"type": "subscribe","product_ids": ["BTC-USD"],"channels": ["ticker","heartbeat"]}')
while (true) {
var msgBinance = binance.read(-1)
var msgCoinbase = coinbase.read(-1)
if(msgBinance){
// Binance has new data
}
if(msgCoinbase){
// coinbase has new data
}
Sleep(1) // just sleep 1ms
}
}
Rangka kerja umum untuk menggunakan websocket
Oleh kerana data push telah digunakan, program secara semula jadi ditulis sebagai jenis yang didorong oleh peristiwa, memberi perhatian kepada kekerapan permintaan API.
var tradeTime = Date.now()
var accountTime = Date.now()
function trade(data){
if(Date.now() - tradeTime > 2000){//only trade once within 2s
tradeTime = Date.now()
//trading code
}
}
function GetAccount(){
if(Date.now() - accountTime > 5000){//only get account once within 5s
accountTime = Date.now()
return exchange.GetAccount()
}
}
function main() {
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr|reconnect=true")
while (true) {
var msg = client.read()
var data = JSON.parse(msg)
var account = GetAccount()
trade(data)
}
}
Semua parameter
ParameterDial(Address, Timeout)
:
Timeout
: masa cuti sambungan
Alamat boleh diikuti oleh parameter lain yang berkaitan dengan&
. Alamat dan parameter dipisahkan oleh|
,
Parameter | Penerangan |
---|---|
memampatkan | Kaedah mampatan, bolehgzip_raw , gzip . Penggunaan OKEXgzip_raw |
mod | bolehdual bermakna kedua-dua menghantar dan menerima perlu dimampatkan,send bermakna menghantar perlu ditekan danrecv Bermakna menerima. |
penggantinya | tetapan proksi untuk ss5.socks5://name:pwd@192.168.0.1:1080 |
sambung semula | Reconnect=true untuk membolehkan sambungan semula |
Jangkaan | interval adalah selang percubaan semula, lalai adalah 1000ms |
muatan | Mesej langganan yang perlu dihantar apabila wss menyambung semula |
Parameterread()
:
Apabila websocket disconnected,read()
akan mengembalikan rentetan kosong.
Parameter | Tiada | -1 | -2 | 2000 |
---|---|---|---|---|
barisan tidak kosong | mengembalikan data tertua dengan segera | mengembalikan data tertua dengan segera | Kembalikan data terkini dengan segera | mengembalikan data tertua dengan segera |
barisan kosong | Blokkan sehingga data baru kembali | Kembalinull segera |
Kembalinull segera |
tunggu kurang daripada 2000ms sehingga data baru kembali, jika tidak, kembalinull |
Penggunaanclose()
:
Tutup sambungan websocket.
function main() {
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr|reconnect=true")
client.close()
}
Anda mungkin telah melihat semua kod yang kita ada sekarang adalah satu benang, pelaksanaan berturut-turut. JavaScript mentah tidak menyokong asynchronous, bagaimanapun, FMZ menyediakan fungsiGO
untuk melakukan itu, yang sangat terhad.Go
apabila anda benar-benar mengambil berat tentang kelewatan dan penggunaan masa setiap permintaan API.
pertukaran.Go ((Method, Args)
Kaedah: nama fungsi. Args: Args kaedah.
Senarai fungsi yang disokong:GetTicker
, GetDepth
, GetTrades
, GetRecords
, GetAccount
, GetOrders
, GetOrder
, CancelOrder
, Buy
, Sell
, GetPosition
.
Contoh JavaScript:
function main(){
var a = exchange.Go("GetTicker"); //GetTicker Asynchronous multithreaded execution
var b = exchange.Go("GetDepth");
var c = exchange.Go("Buy", 1000, 0.1);
var d = exchange.Go("GetRecords", PERIOD_H1);
// The above four operations are concurrent multi-threaded asynchronous execution, will not block and immediately return
var ticker = a.wait(); // Call wait method wait for return to asynchronous get ticker result
var depth = b.wait(); // Return depth, it is also possible to return null if it fails
var orderId = c.wait(1000); // Return the order number, 1 second timeout, timeout returns undefined, this object can continue to call wait until the last wait timeout
var records = d.wait(); // Wait for K-line result
var ret = d.wait(); // Here waits for an asynchronous operation that has waited and ended, returns null, and logs an error message.
}
wait()
fungsi mesti dipanggil selepasGo
fungsi, jika tidak, sumber thread akan terkumpul sehingga tahun 2000 dan mengembalikan ralat.
LogStatus
dan Jadual
LogStatus akan Log mesej atau jadual pada bar status bot, akan menyegarkan setiap kali.
//Normal uses of LogStatus
LogStatus(" This is a normal status prompt")
LogStatus(" This is a red font status prompt #ff0000")
LogStatus(" This is a multi-line status message\n I'm the second line")
LogStatus boleh log jadual pada halaman robot anda.`
karakter ke kedua-dua belah pihak dan memperlakukannya sebagai format mesej yang kompleks (jadual yang kini disokong).
var table = {type: 'table', title: ' Account information support color #ff0000', cols: ['BTC', 'ETH', 'USDT'], rows: [ ['free', 1, 2000], ['frozen', 0, 3000]]}
LogStatus('`' + JSON.stringify(table)+'`')
//Another example, information can also appear in multiple lines:
LogStatus("First line message\n" + JSON.stringify(table)+"`\n third line message")
//Log multiple tables in a group, switching by TAB:
var table1 = {type: 'table', title: ' Account information 1', cols: ['BTC', 'ETH', 'USDT'], rows: [ ['free', 1, 2000], ['frozen', 0, 3000]]}
var table2 = {type: 'table', title: ' Account information 2', cols: ['BTC', 'ETH', 'USDT'], rows: [ ['free', 1, 2000], ['frozen', 0, 3000]]}
LogStatus('`' + JSON.stringify([table1, table2])+'`')
Jadual
Lukis angka pada halaman pengurusan robot.
Sokongan carta HighStocks dan HighCharts, semakhttps://www.highcharts.com/demodanhttps://www.highcharts.com/stock/demountuk lebih banyak contoh.
Objek Chart mempunyai__isStock
atribut yang tidak wujud dalam yang asal. Jika__isStock
adalah false, carta akan dipaparkan sebagai HighCharts.__isStock
adalah benar, carta akan dipaparkan sebagai HighStocks.reset()
untuk membersihkan data carta.
Contoh JavaScript menggunakan Carta untuk menarik harga dua simbol:
// This chart is an object in the JS language. Before using the Chart function, we need to declare an object variable chart that configures the chart.
var chart = {
// Whether the mark is a general chart, if you are interested, you can change it to false and run it.
__isStock: true,
tooltip: {xDateFormat: '%Y-%m-%d %H:%M:%S, %A'}, // Zoom tool
title : { text : 'Spread Analysis Chart'}, // title
rangeSelector: { // Selection range
buttons: [{type: 'hour',count: 1, text: '1h'}, {type: 'hour',count: 3, text: '3h'}, {type: 'hour', count: 8, text: '8h'}, {type: 'all',text: 'All'}],
selected: 0,
inputEnabled: false
},
xAxis: { type: 'datetime'}, // The horizontal axis of the coordinate axis is the x axis and the current setting type is :time
yAxis : { // The vertical axis of the axis is the y axis, and the default value is adjusted with the data size.
title: {text: 'Spread'}, // title
opposite: false, // Whether to enable the right vertical axis
},
series : [ // Data series, this attribute is saved for each data series (line, K-line graph, label, etc...)
{name : "line1", id : "Line 1,buy1Price", data : []}, // The index is 0, the data array is stored in the index series of data
{name : "line2", id : "Line 2,lastPrice", dashStyle : 'shortdash', data : []},
// The index is 1, dashStyle is set: 'shortdash' ie: Set the dotted line.
]
};
function main(){
var ObjChart = Chart(chart); // Call the Chart function to initialize the chart.
ObjChart.reset(); // Empty the chart
while(true){
var nowTime = new Date().getTime(); // Get the timestamp of this poll, which is a millisecond timestamp. Used to determine the position of the X axis written to the chart.
var tickerOne = _C(exchanges[0].GetTicker); // Get market data
var tickerTwo = _C(exchanges[1].GetTicker);
ObjChart.add([0, [nowTime, tickerOne.Last]]); // Use the timestamp as the X value and buy the price as the Y value to pass the index 0 data sequence.
ObjChart.add([1, [nowTime, tickerTwo.Last]]); // Same as above
ObjChart.update(chart); // Update the chart to show it.
Sleep(2000);
}
}
Menyokong paparan pelbagai angka, contoh lengkap:https://www.fmz.com/strategy/136056
Template adalah perpustakaan yang merangkumi banyak ciri lanjutan, yang memudahkan menulis strategi anda. Untuk menggunakan templat, anda harus menyalin templat yang anda perlukan terlebih dahulu. Ambil perpustakaan JavaScript Plot sebagai contoh, salin darihttps://www.fmz.com/strategy/27293dan simpan. Kemudian pilih pada halaman edit strategi.Fungsi dipanggil selepas$.
dalam templat JavaScript dan selepasext.
dalam templat Python.
function main() {
var isFirst = true
while (true) {
var records = exchange.GetRecords();
if (records && records.length > 0) {
$.PlotRecords(records, 'BTC')
if (isFirst) {
$.PlotFlag(records[records.length - 1].Time, 'Start', 'S')
isFirst = false
$.PlotHLine(records[records.length - 1].Close, 'Close')
}
}
var ticker = exchange.GetTicker()
if (ticker) {
$.PlotLine('Last', ticker.Last)
$.PlotTitle('Last ' + ticker.Last)
}
Sleep(60000)
}
}
Berikut adalah satu lagi contoh mudah yang menggunakan templat plot:https://www.fmz.com/strategy/121917
q25459768Terima kasih.
RumputSaya sedang bekerja pada tutorial ini. Ia akan mengambil masa beberapa hari untuk menyelesaikan. berasa bebas untuk bertanya apa-apa soalan.