[TOC] Sebelum belajar tutorial ini, anda perlu belajarMulakan dengan Platform FMZ QuantdanTutorial asas untuk platform FMZ Quant Strategy Writing, dan menguasai bahasa pengaturcaraan.Tutorial asas merangkumi fungsi yang paling biasa digunakan, tetapi terdapat banyak fungsi dan ciri yang belum diperkenalkan, dan mereka tidak akan dilindungi dalam tutorial ini.Selepas mempelajari tutorial ini, anda akan dapat menulis lebih banyak strategi percuma dan disesuaikan, dan platform FMZ Quant hanyalah alat.
Platform FMZ Quant merangkumi semua platform yang disokong. Untuk mengekalkan keseragaman, sokongan kami untuk API platform tunggal masih tidak lengkap. Sebagai contoh, GetRecords boleh menyampaikan jumlah K-line atau masa permulaan, sementara ia tetap pada platform FMZ; beberapa platform menyokong pesanan batch, sementara FMZ tidak menyokongnya, dan sebagainya. Jadi terdapat keperluan untuk cara untuk mengakses data platform secara langsung.Untuk antara muka awam (seperti sebut harga pasaran), anda boleh menggunakanHttpQuery
, dan untuk antara muka yang disulitkan (yang melibatkan maklumat akaun), anda perlu menggunakanIO
.Untuk parameter masuk tertentu, sila rujuk dokumen API platform yang sepadan.Info
medan mengembalikan maklumat mentah, tetapi ia masih tidak membuat perbezaan pada masalah tidak menyokong antara muka.
Ia mengembalikan kandungan mentah (string) yang diminta oleh API REST terakhir, yang boleh digunakan untuk menganalisis maklumat lanjutan dengan sendirinya.
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)
}
Untuk mengakses antara muka awam, Js boleh menggunakanHttpQuery
, dan Python boleh menggunakan pakej yang berkaitan, sepertiurllib
ataurequests
.
HttpQuery lalai kepada kaedah GET, dan menyokong lebih banyak fungsi; lihat dokumen API untuk maklumat lanjut.
var exchangeInfo = JSON.parse(HttpQuery('https://api.binance.com/api/v1/exchangeInfo'))
Log(exchangeInfo)
var ticker = JSON.parse(HttpQuery('https://api.binance.com/api/v1/ticker/24hr'))
var kline = JSON.parse(HttpQuery("https://www.quantinfo.com/API/m/chart/history?symbol=BTC_USD_BITFINEX&resolution=60&from=1525622626&to=1561607596"))
Contoh Python menggunakan permintaan:
import requests
resp = requests.get('https://www.quantinfo.com/API/m/chart/history?symbol=BTC_USD_BITFINEX&resolution=60&from=1525622626&to=1561607596')
data = resp.json()
Untuk antara muka yang memerlukan tandatangan API-KEY, fungsi IO boleh digunakan, dan pengguna hanya perlu mengambil berat tentang parameter masuk, dan proses tandatangan tertentu akan diselesaikan oleh lapisan bawah.
Platform FMZ pada masa ini tidak menyokong pesanan stop-loss BitMEX, yang boleh dilaksanakan melalui IO, mengikut langkah-langkah berikut:
https://www.bitmex.com/api/explorer/
;https://www.bitmex.com/api/v1/order
, dengan kaedahPOST
; untuk FMZ telah menentukan alamat pangkalan secara dalaman, anda hanya perlu menghantar symbol=XBTUSD&side=Buy&orderQty=1&stopPx=4000&ordType=Stop
.Kod khusus:
var id = exchange.IO("api", "POST", "/api/v1/order", "symbol=XBTUSD&side=Buy&orderQty=1&stopPx=4000&ordType=Stop")
// You can also pass in the object
var id = exchange.IO("api", "POST", "/api/v1/order", "", JSON.stringify({symbol:"XBTUSD",side:"Buy",orderQty:1,stopPx:4000,ordType:"Stop"}))
Lebih banyak contoh IO:https://www.fmz.com/bbs-topic/3683
Pada asasnya, semua platform cryptocurrency menyokong websocket untuk menghantar sebut harga pasaran, dan beberapa platform menyokong websocket untuk mengemas kini maklumat akaun. Berbanding dengan API rehat, websocket umumnya mempunyai kelebihan, seperti latensi rendah, frekuensi tinggi dan tidak terhad oleh frekuensi API rehat platform, dll. Kelemahannya adalah bahawa terdapat masalah gangguan, yang pemprosesannya tidak intuitif.
Artikel ini terutamanya akan memperkenalkan cara menggunakan bahasa JavaScript dan cara menggunakan fungsi Dial yang dikapsulkan oleh platform untuk menyambung, pada platform FMZ Quant; untuk arahan dan parameter tertentu terdapat dalam dokumen, anda boleh mencari Dial; untuk merealisasikan pelbagai fungsi, fungsi Dial telah dikemas kini beberapa kali. Artikel ini akan merangkumi dan memperkenalkan strategi yang didorong peristiwa berdasarkan wss, serta isu menyambung beberapa platform. Python juga boleh menggunakan fungsi Dial, atau perpustakaan yang sesuai.
Secara amnya, menyambung secara langsung melalui Websocket; contohnya untuk mendapatkan dorongan penipu Binance:
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
Jika data yang dikembalikan adalah dalam format yang dimampatkan, spesifikasi harus dibuat semasa menyambung;
var client = Dial("wss://real.okex.com:10441/websocket?compress=true|compress=gzip_raw&mode=recv")
Fungsi Dial menyokong sambungan semula, yang dilakukan oleh Golang yang mendasari. Jika sambungan yang dikesan rosak, ia akan disambungkan semula. Untuk data permintaan yang sudah ada di url, seperti contoh Binance sekarang, ia sangat mudah dan disyorkan. Bagi mereka yang perlu menghantar mesej langganan, mereka boleh mengekalkan mekanisme sambungan semula sendiri.
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr|reconnect=true")
Untuk melanggan mesej wss, beberapa permintaan platform berada di url, dan beberapa memerlukan untuk menghantar saluran yang melanggan sendiri, seperti coinbase:
client = Dial("wss://ws-feed.pro.coinbase.com", 60)
client.write('{"type": "subscribe","product_ids": ["BTC-USD"],"channels": ["ticker","heartbeat"]}')
Secara amnya, websocket digunakan untuk membaca sebut harga pasaran, tetapi ia juga boleh digunakan untuk mendapatkan pesanan dan memaksa akaun. Memaksa data yang disulitkan kadang-kadang mempunyai kelewatan yang panjang dan harus digunakan dengan berhati-hati. Oleh kerana kaedah penyulitan lebih rumit, berikut adalah beberapa contoh yang diberikan untuk rujukan. Perhatikan bahawa hanya AccessKey diperlukan, yang boleh ditetapkan sebagai parameter strategi. Jika SecretKey diperlukan, ia boleh dipanggil secara tersirat oleh fungsi pertukaran.HMAC() untuk memastikan keselamatan.
//Push example of Huobi Futures
var ACCESSKEYID = 'accesskey of your Huobi account'
var apiClient = Dial('wss://api.hbdm.com/notification|compress=gzip&mode=recv')
var date = new Date();
var now_utc = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(),date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
var utc_date = new Date(now_utc)
var Timestamp = utc_date.toISOString().substring(0,19)
var quest = 'GET\napi.hbdm.com\n/notification\n'+'AccessKeyId='+ACCESSKEYID+'&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=' + encodeURIComponent(Timestamp)
var signature = exchange.HMAC("sha256", "base64", quest, "{{secretkey} }") // Remove the extra blank spaces between }}
auth = {op: "auth",type: "api",AccessKeyId: ACCESSKEYID, SignatureMethod: "HmacSHA256",SignatureVersion: "2", Timestamp: Timestamp, Signature:encodeURI(signature)}
apiClient.write(JSON.stringify(auth))
apiClient.write('{"op": "sub","cid": "orders","topic": "orders.btc'}')
while (true){
var data = datastream.read()
if('op' in data && data.op == 'ping'){
apiClient.write(JSON.stringify({op:'pong', ts:data.ts}))
}
}
// Push example of Binance; pay attention that listenKey needs to be updated regularly
var APIKEY = 'accesskey of your Binance account'
var req = HttpQuery('https://api.binance.com/api/v3/userDataStream',{method: 'POST',data: ''},null,'X-MBX-APIKEY:'+APIKEY);
var listenKey = JSON.parse(req).listenKey;
HttpQuery('https://api.binance.com/api/v3/userDataStream', {method:'DELETE',data:'listenKey='+listenKey}, null,'X-MBX-APIKEY:'+APIKEY);
listenKey = JSON.parse(HttpQuery('https://api.binance.com/api/v3/userDataStream','',null,'X-MBX-APIKEY:'+APIKEY)).listenKey;
var datastream = Dial("wss://stream.binance.com:9443/ws/"+listenKey+'|reconnect=true',60);
var update_listenKey_time = Date.now()/1000;
while (true){
if (Date.now()/1000 - update_listenKey_time > 1800){
update_listenKey_time = Date.now()/1000;
HttpQuery('https://api.binance.com/api/v3/userDataStream', {method:'PUT',data:'listenKey='+listenKey}, null,'X-MBX-APIKEY:'+APIKEY);
}
var data = datastream.read()
}
// push example of BitMEX
var APIKEY = "your Bitmex API ID"
var expires = parseInt(Date.now() / 1000) + 10
var signature = exchange.HMAC("sha256", "hex", "GET/realtime" + expires, "{{secretkey} }")// secretkey is automatically replaced during execution, so no need to fill in
var client = Dial("wss://www.bitmex.com/realtime", 60)
var auth = JSON.stringify({args: [APIKEY, expires, signature], op: "authKeyExpires"})
var pos = 0
client.write(auth)
client.write('{"op": "subscribe", "args": "position"}')
while (true) {
bitmexData = client.read()
if(bitmexData.table == 'position' && pos != parseInt(bitmexData.data[0].currentQty)){
Log('position change', pos, parseInt(bitmexData.data[0].currentQty), '@')
pos = parseInt(bitmexData.data[0].currentQty)
}
}
Secara amnya, ia boleh dibaca secara berterusan dalam gelung yang tidak berkesudahan.
function main() {
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr");
while (true) {
var msg = client.read()
var data = JSON.parse(msg) // Parse json strings into quotable objects
// Process data
}
}
kelajuan push data wss sangat cepat. lapisan bawah Golang akan cache semua data dalam antrian, dan apabila panggilan program dibaca, data akan dikembalikan. Walau bagaimanapun, operasi seperti meletakkan pesanan pada bot akan menyebabkan kelewatan, yang mungkin mengakibatkan pengumpulan data. Untuk maklumat seperti dorongan pelaksanaan perdagangan, dorongan akaun, dan dorongan interpolasi kedalaman, kita memerlukan data sejarah. Untuk data pasaran sebut harga, dalam kebanyakan kes, kita hanya peduli dengan data terkini, bukan data sejarah.
Jikaread()
jika tidak menambah parameter, ia akan mengembalikan data tertua, dan blok sehingga kembali apabila tidak ada data.client.read(-2)
untuk mengembalikan data terkini dengan segera, tetapi apabila tidak ada data, ia akan mengembalikan null, yang perlu dinilai sebelum rujukan.
Bergantung pada cara menangani data cache lama dan sama ada ia disekat apabila tidak ada data,
Dalam kes ini, adalah jelas bahawa hanya menggunakan
function main() {
var binance = Dial("wss://stream.binance.com:9443/ws/!ticker@arr");
var coinbase = Dial("wss://ws-feed.pro.coinbase.com", 60)
coinbase.write('{"type": "subscribe","product_ids": ["BTC-USD"],"channels": ["ticker","heartbeat"]}')
while (true) {
var msgBinance = binance.read(-1) // Parameter -1 represents no data and return null immediately; it will not occur that being blocked before there is data to be returned
var msgCoinbase = coinbase.read(-1)
if(msgBinance){
// at this time, Binance has data to return
}
if(msgCoinbase){
// at this time, coinbase has data to return
}
Sleep(1) // Sleep for 1 millisecond
}
}
Bahagian pemprosesan ini lebih menyusahkan, kerana data push mungkin terganggu, atau kelewatan push sangat lama. Walaupun detak jantung dapat diterima, itu tidak bermakna data masih didorong. Anda boleh menetapkan selang acara; jika tidak ada kemas kini yang diterima selepas selang waktu, sambung semula; adalah lebih baik untuk membandingkan hasil yang dikembalikan oleh
Untuk data dorong telah digunakan, program secara semula jadi akan ditulis sebagai acara-dihidupkan; memberi perhatian kepada kekerapan data dorong, kerana permintaan frekuensi tinggi akan menyebabkan disekat; secara amnya anda boleh menulis:
var tradeTime = Date.now()
var accountTime = Date.now()
function trade(data){
if(Date.now() - tradeTime > 2000){//Here it limits only one trade in 2 seconds
tradeTime = Date.now()
// Trading logic
}
}
function GetAccount(){
if(Date.now() - accountTime > 5000){//Here it limits GetAccount only once in 5 seconds
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)
}
}
Kaedah sambungan, kaedah penghantaran data, kandungan langganan dan format data websocket pada setiap platform sering berbeza, jadi platform tidak mengkapsulkannya dan perlu menggunakan fungsi Dial untuk menyambung sendiri.
PS: Walaupun beberapa platform tidak menyediakan petikan websocket, sebenarnya, apabila anda log masuk ke laman web untuk menggunakan fungsi debugging, anda akan mendapati bahawa mereka semua menggunakan websocket push.
JavaScript boleh merealisasikan kecocokan oleh fungsi Go, dan Python boleh menggunakan perpustakaan multithread yang sepadan.
Semasa merealisasikan strategi kuantitatif, pelaksanaan serentak dapat mengurangkan kelewatan masa dan meningkatkan kecekapan. Ambil bot strategi lindung nilai sebagai contoh. Ia perlu mendapatkan kedalaman dua syiling, dan kod yang dilaksanakan mengikut urutan ditunjukkan sebagai:
var depthA = exchanges[0].GetDepth()
var depthB = exchanges[1].GetDepth()
Apabila permintaan API rehat ditangguhkan, contohnya masa kelewatan adalah 100 milisaat, maka masa untuk mendapatkan kedalaman dua kali sebenarnya berbeza; jika lebih banyak akses diperlukan, masalah kelewatan akan lebih jelas, yang akan mempengaruhi pelaksanaan strategi.
Oleh kerana JavaScript tidak mempunyai multithread, lapisan bawah merangkumi fungsi Go untuk menyelesaikan masalah ini. fungsi Go boleh digunakan untuk API yang memerlukan akses rangkaian, sepertiGetDepth
, GetAccount
dan seterusnya.IO
juga disokong, seperti:exchange.Go("IO", "api", "POST", "/api/v1/contract_batchorder", "orders_data=" + JSON.stringify(orders))
, tetapi kerana mekanisme reka bentuk, ia lebih membosankan untuk dilaksanakan.
var a = exchanges[0].Go("GetDepth")
var b = exchanges[1].Go("GetDepth")
var depthA = a.wait() // Call "wait" method to wait for the return of the asynchronous GetDepth result
var depthB = b.wait()
Dalam kebanyakan kes yang mudah, menulis strategi dengan cara ini baik-baik saja. Tetapi perhatikan bahawa proses itu diulangi setiap kali strategi gelung, dan pemboleh ubah perantara a dan b sebenarnya hanya sementara tambahan. Jika kita mempunyai banyak tugas serentak, kita perlu tambahan merakam korespondensi antara a dan kedalamanA, b dan kedalamanB. Apabila tugas serentak kita tidak pasti, situasi lebih rumit. Oleh itu, kita berharap untuk merealisasikan fungsi: apabila menulis fungsi Go serentak, mengikat pemboleh ubah pada masa yang sama; apabila hasil berjalan serentak kembali, nilai hasil secara automatik diberikan kepada pemboleh ubah, dengan itu menghapuskan keperluan untuk membuat pemboleh ubah perantara dan program lebih ringkas. Pelaksanaan khusus adalah seperti berikut:
function G(t, ctx, f) {
return {run:function(){
f(t.wait(1000), ctx)
}}
}
Kami menentukan fungsi G, di mana parameter
Pada masa ini, kerangka kerja program keseluruhan boleh ditulis sebagai model, serupa dengan model
var Info = [{depth:null, account:null}, {depth:null, account:null}] // If we need to obtain the depth and account of the two platforms, more information can also be put in, such as order ID and status, etc.
var tasks = [ ] // Global task list
function produce(){ // Issue all kinds of concurrent tasks
// Here the task producing logic has been omitted, only for demo
tasks.push({exchange:0, ret:'depth', param:['GetDepth']})
tasks.push({exchange:1, ret:'depth', param:['GetDepth']})
tasks.push({exchange:0, ret:'sellID', param:['Buy', Info[0].depth.Asks[0].Price, 10]})
tasks.push({exchange:1, ret:'buyID', param:['Sell', Info[1].depth.Bids[0].Price, 10]})
}
function worker(){
var jobs = []
for(var i=0;i<tasks.length;i++){
var task = tasks[i]
jobs.push(G(exchanges[task.exchange].Go.apply(this, task.param), task, function(v, task) {
Info[task.exchange][task.ret] = v // Here "v" is the return value of the concurrent Go function "wait()", and you can think about it
}))
}
_.each(jobs, function(t){
t.run() // Here all tasks are executed concurrently
})
tasks = []
}
function main() {
while(true){
produce() // Give trading command
worker() // Concurrently execute
Sleep(1000)
}
}
Ia kelihatan bahawa hanya fungsi mudah telah dilaksanakan dalam operasi di atas. Sebenarnya, yang telah sangat memudahkan kerumitan kod. Kita hanya perlu mengambil berat tentang apa tugas yang perlu dihasilkan oleh program, dan
Dalam tutorial asas, perpustakaan kelas lukisan disyorkan dalam pengenalan lukisan, yang dapat memenuhi keperluan dalam kebanyakan kes.
Parameter dalamanChart({…})
adalah objek HighStock dan HighCharts, tetapi parameter tambahan__isStock
FMZ pada dasarnya menyokong modul asas HighCharts dan HighStock, tetapi tidak menyokong modul tambahan.
Contoh HighCharts khusus:https://www.highcharts.com/demo; Contoh HighStock:https://www.highcharts.com/stock/demo. Anda boleh merujuk kepada kod dalam contoh-contoh itu, dan memindahkan mereka ke FMZ mudah.
Anda boleh memanggil add ([indeks siri ((seperti 0), data]) untuk menambah data ke dalam siri dengan indeks yang ditentukan. Panggil reset() untuk membersihkan data carta; reset boleh mengambil parameter nombor dan menentukan jumlah yang akan disimpan. Penampilan carta berbilang disokong, yang hanya perlu lulus dalam parameter array semasa konfigurasi, seperti: var chart = Chart (([{...}, {...}, {...}]). Sebagai contoh, jika Carta1 mempunyai dua siri, Carta2 mempunyai satu siri, dan Carta3 mempunyai satu siri, apabila memanggil add, ID siri 0 dan 1 ditentukan untuk mewakili data kedua siri secara berasingan dalam Carta1 yang dikemas kini; siri 2 ditentukan untuk mewakili data siri pertama dalam Carta2; siri ID 3 ditentukan untuk mewakili siri pertama dalam Carta3.
Contoh khusus:
var chart = { // This "chart" in JS is an object; before using the Chart function, we need to declare the object variable of a configured chart "chart"
__isStock: true, // Mark whether it is a general chart; you can change it to false and try to operate it, if you are interested
tooltip: {xDateFormat: '%Y-%m-%d %H:%M:%S, %A'}, // Zoom tool
title : { text : 'spread chart'}, // Theme
rangeSelector: { // Choose the 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'}, // Horizontal axis, namely X axis; currently set type: time
yAxis : { // Vertical axis, namely Y axis; the default changes according to the data
title: {text: 'spread'}, // Theme
opposite: false, // whether to enable the vertical axis on the right
},
series : [ // Data series; the attribute saves all kinds of data series (lines, K-lines, labels, etc.)
{name : "line1", id : "line1,buy1Price", data : []}, // The index is 0; the data stroed in the data array is the data of the index series
{name : "line2", id : "line2,lastPrice", dashStyle : 'shortdash', data : []}, // The index is 1; set dashStyle: 'shortdash', namely: set dashed line
]
};
function main(){
var ObjChart = Chart(chart); // Call the Chart function, and initialize the chart
ObjChart.reset(); // Empty
while(true){
var nowTime = new Date().getTime(); // Obtain the timestamp of this polling, namely a millisecond tiemstamp, to ensure the location of writing to the X axis in the chart
var ticker = _C(exchange.GetTicker); // Obtain the market quotes data
var buy1Price = ticker.Buy; // Get buy one price from the return value of the market quotes
var lastPrice = ticker.Last + 1; // Get the final executed price, and we add 1 to split the 2 lines
ObjChart.add([0, [nowTime, buy1Price]]); // Use the timestamp as the value of X, and buy one price as the value of Y; pass in the data series of index 0
ObjChart.add([1, [nowTime, lastPrice]]); // Same as above.
Sleep(2000);
}
}
Contoh penggunaan susun atur carta:https://www.fmz.com/strategy/136056
Alamat sumber terbuka khusus:https://github.com/fmzquant/backtest_python
Pemasangan
Masukkan arahan berikut dalam baris arahan:
pip install https://github.com/fmzquant/backtest_python/archive/master.zip
Contoh Sederhana
Tetapkan parameter backtest di awal kod strategi dalam bentuk komen, dan butiran akan dipaparkan di butang
'''backtest
start: 2018-02-19 00:00:00
end: 2018-03-22 12:00:00
period: 15m
exchanges: [{"eid":"OKEX","currency":"LTC_BTC","balance":3,"stocks":0}]
'''
from fmz import *
task = VCtx(__doc__) # initialize backtest engine from __doc__
print exchange.GetAccount()
print exchange.GetTicker()
print task.Join() # print backtest result
Ujian belakang
Untuk strategi yang lengkap memerlukan gelung tanpa akhir, kesilapan EOF akan dibangkitkan selepas backtest selesai; oleh itu, kita harus melakukan toleransi ralat dengan baik.
# !/usr/local/bin/python
# -*- coding: UTF-8 -*-
'''backtest
start: 2018-02-19 00:00:00
end: 2018-03-22 12:00:00
period: 15m
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD","balance":10000,"stocks":3}]
'''
from fmz import *
import math
import talib
task = VCtx(__doc__) # initialize backtest engine from __doc__
# ------------------------------ Start of the Strategy --------------------------
print exchange.GetAccount() # Call some interfaces, and print their return values
print exchange.GetTicker()
def adjustFloat(v): # the custom functions in the strategy
v = math.floor(v * 1000)
return v / 1000
def onTick():
Log("onTick")
# Specific strategy code
def main():
InitAccount = GetAccount()
while True:
onTick()
Sleep(1000)
# ------------------------------ End of the Strategy --------------------------
try:
main() # The end of the backtest will raise EOFError() to stop stop the backtest loop. Therefore, we should handle with the error, and call task.Join() to print the backtest result, after the error is detected
except:
print task.Join()
exchange.SetData(arr) menukar sumber data backtest dan menggunakan data K-line tersuai. Parameter
dalam array arr, format data elemen tunggal:
[
1530460800, // time Timestamp
2841.5795, // open Open Price
2845.6801, // high Highest Price
2756.815, // low Lowest Price
2775.557, // close Close Price
137035034 // volume Executed Volume
]
Sumber data boleh diimport dalam
function init() { // The init function in the template will be executed first when the template is loaded; ensure the exchange.SetData(arr) function is executed first, initialized, and set the data to the backtest system
var arr = [ // The K-line data to be used during backtest
[1530460800,2841.5795,2845.6801,2756.815,2775.557,137035034], // The data of the earliest K-line bar
... , // If the K-line data is too long, use "..." to represent the omitted data here
[1542556800,2681.8988,2703.5116,2674.1781,2703.5116,231662827] // The data of the latest K-line bar
]
exchange.SetData(arr) // Import the custom data mentioned above
Log("Import data successfully")
}
Nota: pastikan untuk mengimport data tersuai terlebih dahulu (iaitu, panggil fungsi exchange.SetData untuk menetapkan data) semasa inisialisasi. Tempoh data K-garis tersuai mestilah konsisten dengan tempoh K-garis bawah yang ditetapkan pada halaman backtest, iaitu: data K-garis tersuai; masa K-garis adalah 1 minit, jadi tempoh K-garis bawah yang ditetapkan dalam backtest juga harus ditetapkan menjadi 1 minit.
Jika API platform yang tidak disokong adalah sama dengan platform yang disokong, kecuali alamat pangkalan, platform yang tidak disokong boleh disokong dengan menukar alamat pangkalan. Untuk lebih spesifik, pilih platform yang disokong apabila menambah platform, tetapi isi API-KEY platform yang tidak disokong, dan gunakan IO untuk menukar alamat pangkalan dalam strategi, seperti:
exchange.IO("base", "http://api.huobi.pro")
//http://api.huobi.pro is the base address of the unsupported platform API, and notice not to add api/v3 and so on, for the address will be automatically completed
Tidak semua platform disokong oleh FMZ, tetapi platform kami telah menyediakan kaedah akses protokol umum.
Secara ringkasnya, protokol umum adalah seperti perantara, melampirkan permintaan docker dan mengembalikan data, mengikut standard yang sesuai. Kod protokol umum perlu disiapkan sendiri. Menulis protokol umum sebenarnya bermakna anda boleh mengakses platform semata-mata dan menyelesaikan strategi. FMZ rasmi kadang-kadang mengeluarkan versi exe protokol umum platform. Protokol umum juga boleh dilakukan dalam Python, yang kemudian boleh dijalankan di docker sebagai bot biasa.
Pengenalan khusus protokol umum:https://www.fmz.com/bbs-topic/9120Contoh penulisan protokol umum dalam Python:https://www.fmz.com/strategy/101399
Sama seperti pelbagai operasi platform boleh dilaksanakan melalui API, laman web FMZ juga berdasarkan API. Anda boleh memohon API-KEY laman web FMZ anda sendiri untuk merealisasikan fungsi, seperti
Oleh kerana kebolehluasan kuat platform FMZ Quant, anda boleh membuat platform kuantitatif anda sendiri berdasarkan sambungan API, membolehkan pengguna anda menjalankan bot di platform anda, dll. Rujukan khusus:https://www.fmz.com/bbs-topic/1697 .
Pasaran perdagangan mata wang kripto telah menarik lebih banyak perhatian daripada peniaga kuantitatif kerana keunikannya. Sebenarnya, perdagangan program telah menjadi arus perdana mata wang kripto, dan strategi seperti lindung nilai dan pembuatan pasaran selalu aktif di pasaran. Pemula dengan asas pengaturcaraan yang lemah ingin memasuki bidang baru ini, berhadapan dengan banyak platform dan API yang berubah, penuh dengan kesukaran.www.fmz.comUntuk mengambil kursus di NetEase, anda hanya memerlukan 20 yuan, dan kursus ini sepenuhnya untuk pemula.
PemberdayaanKursus Perdagangan Kuantitatif Cryptocurrency di NetEase Cloud Classroom. Log masuk ke NetEase Cloud Classroom dan kongsi pautan kursus anda (pautan ini mempunyai ID kursus yang unik). Yang lain, yang mendaftar dan membeli kursus melalui pautan ini, akan membawa anda 50% daripada jumlah keseluruhan sebagai komisen, iaitu 10 yuan. Ikuti akaun awam WeChat
Pengguna yang mengklik pautan promosi, mendaftar dan mengecas semula dalam tempoh setengah tahun, akan menikmati dasar bahawa syarikat kami akan memberi diskaun mengikut jumlah yang berkesan dalam pesanan yang sah. Suruhanjaya akan dikembalikan ke akaun promoter dalam bentuk mata. Pengguna boleh menukar mata ke baki akaun platform FMZ pada nisbah 10: 1, dan pengguna juga boleh menggunakan mata untuk menukar produk berkaitan FMZ Quant pada masa akan datang. Pautan khusus untuk aktiviti:https://www.fmz.com/bbs-topic/3828
Laman web FMZ lengkap boleh digunakan pada pelayan eksklusif perusahaan atau pasukan untuk kawalan lengkap dan penyesuaian fungsi. Laman web FMZ telah digunakan dan diuji oleh kira-kira 100,000 pengguna, dan telah mencapai ketersediaan dan keselamatan yang tinggi, yang dapat menjimatkan masa untuk pasukan kuantitatif dan perusahaan. Versi perusahaan adalah untuk pasukan perdagangan kuantitatif bersaiz sederhana, penyedia perkhidmatan niaga hadapan komoditi, dll. Sila hubungi pentadbir untuk sebut harga khusus.
Sistem profesional, menyediakan kecairan pasaran dan pengurusan dana untuk platform, mungkin merupakan sistem pembuatan pasaran yang paling dipertingkatkan di pasaran.
Sistem perdagangan teknologi FMZ mengamalkan teknologi pencocokan memori, dan kelajuan pemprosesan pesanan setinggi 2 juta dagangan sesaat, yang dapat memastikan bahawa tidak akan ada kelewatan atau kelewatan dalam pemprosesan pesanan. Ia dapat mengekalkan operasi yang lancar dan stabil platform dengan lebih daripada 20 juta pengguna dalam talian serentak. Kerangka sistem pelbagai lapisan dan pelbagai klaster memastikan keselamatan, kestabilan dan kebolehluasan sistem. Pengerahan fungsi dan kemas kini versi dapat dilakukan tanpa downtime, yang menjamin pengalaman operasi pengguna terminal maksimum. Pada masa ini, sistem dapat dialami dalam platform simulasi wex.app.