[TOC] Sebelum belajar tutorial ini, Anda perlu belajarMulailah dengan FMZ Quant PlatformdanTutorial dasar untuk FMZ Quant platform Strategy Writing, dan menjadi mahir dalam bahasa pemrograman.Tutorial dasar mencakup fungsi yang paling umum digunakan, tetapi ada banyak fungsi dan fitur yang belum diperkenalkan, dan mereka tidak akan dibahas dalam tutorial ini.Setelah mempelajari tutorial ini, Anda akan dapat menulis lebih banyak strategi gratis dan disesuaikan, dan platform FMZ Quant hanyalah alat.
Platform FMZ Quant merangkum semua platform yang didukung. Untuk menjaga keseragaman, dukungan kami untuk satu platform API masih belum lengkap. Misalnya, GetRecords dapat melewati jumlah K-line atau waktu awal, sementara itu tetap pada platform FMZ; beberapa platform mendukung batch ordering, sementara FMZ tidak mendukung itu, dan sebagainya. Jadi ada kebutuhan untuk cara untuk mengakses data platform secara langsung.Untuk antarmuka publik (seperti penawaran pasar), Anda dapat menggunakanHttpQuery
, dan untuk antarmuka terenkripsi (yang melibatkan informasi akun), Anda perlu menggunakanIO
.Untuk parameter masuk tertentu, silakan lihat dokumen API platform yang sesuai.Info
lapangan mengembalikan informasi mentah, tapi masih tidak membuat perbedaan pada masalah tidak mendukung antarmuka.
Ini mengembalikan konten mentah (string) yang diminta oleh API REST terakhir, yang dapat digunakan untuk menganalisis informasi yang diperluas 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)
}
Untuk mengakses antarmuka publik, Js dapat menggunakanHttpQuery
, dan Python dapat menggunakan paket terkait, sepertiurllib
ataurequests
.
HttpQuery default untuk metode GET, dan mendukung lebih banyak fungsi; periksa dokumen API untuk lebih detail.
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 antarmuka yang membutuhkan tanda tangan API-KEY, fungsi IO dapat digunakan, dan pengguna hanya perlu peduli tentang parameter masuk, dan proses tanda tangan tertentu akan diselesaikan oleh lapisan bawah.
Platform FMZ saat ini tidak mendukung perintah stop loss BitMEX, yang dapat diimplementasikan melalui IO, sesuai dengan langkah-langkah berikut:
https://www.bitmex.com/api/explorer/
;https://www.bitmex.com/api/v1/order
, dengan metodePOST
; untuk FMZ telah secara internal menentukan alamat dasar, Anda hanya perlu memberikan di symbol=XBTUSD&side=Buy&orderQty=1&stopPx=4000&ordType=Stop
.Kode 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 dasarnya, semua platform cryptocurrency mendukung websocket untuk mengirim penawaran pasar, dan beberapa platform mendukung websocket untuk memperbarui informasi akun. Dibandingkan dengan API istirahat, websocket umumnya memiliki keuntungan, seperti latensi rendah, frekuensi tinggi dan tidak dibatasi oleh frekuensi API istirahat platform, dll. Kelemahannya adalah bahwa ada masalah gangguan, yang pengolahannya tidak intuitif.
Artikel ini terutama akan memperkenalkan cara menggunakan bahasa JavaScript dan cara menggunakan fungsi Dial yang dikemas oleh platform untuk terhubung, pada platform FMZ Quant; untuk instruksi dan parameter tertentu ada dalam dokumen, Anda dapat mencari Dial; untuk mewujudkan berbagai fungsi, fungsi Dial telah diperbarui beberapa kali. Artikel ini akan membahas dan memperkenalkan strategi berbasis acara berdasarkan wss, serta masalah menghubungkan beberapa platform. Python juga dapat menggunakan fungsi Dial, atau perpustakaan yang sesuai.
Secara umum, langsung terhubung melalui Websocket; misalnya untuk mendapatkan Binance tricker push:
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
Jika data yang dikembalikan dalam format yang dikompresi, spesifikasi harus dibuat saat menghubungkan;
var client = Dial("wss://real.okex.com:10441/websocket?compress=true|compress=gzip_raw&mode=recv")
Fungsi Dial mendukung koneksi ulang, yang dilakukan oleh Golang yang mendasari. Jika koneksi yang terdeteksi rusak, itu akan dihubungkan kembali. Untuk data permintaan yang sudah ada di url, seperti contoh dari Binance sekarang, ini sangat nyaman dan disarankan. Bagi mereka yang perlu mengirim pesan langganan, mereka dapat mempertahankan mekanisme koneksi ulang sendiri.
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr|reconnect=true")
Untuk berlangganan pesan wss, beberapa permintaan platform ada di url, dan beberapa perlu mengirim saluran yang berlangganan sendiri, seperti coinbase:
client = Dial("wss://ws-feed.pro.coinbase.com", 60)
client.write('{"type": "subscribe","product_ids": ["BTC-USD"],"channels": ["ticker","heartbeat"]}')
Umumnya, websocket digunakan untuk membaca kutipan pasar, tetapi juga dapat digunakan untuk mendapatkan pesanan dan push akun. Push data terenkripsi semacam itu kadang-kadang memiliki keterlambatan yang panjang dan harus digunakan dengan hati-hati. Karena metode enkripsi lebih rumit, berikut adalah beberapa contoh yang diberikan untuk referensi. Perhatikan bahwa hanya AccessKey yang diperlukan, yang dapat ditetapkan sebagai parameter strategi. Jika SecretKey diperlukan, dapat dipanggil secara implisit oleh fungsi exchange.HMAC(() untuk memastikan keamanan.
//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 umum, dapat dibaca terus menerus dalam loop tak terbatas.
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
}
}
Kecepatan push data wss sangat cepat. Lapisan bawah Golang akan cache semua data dalam antrian, dan ketika panggilan program dibaca, data akan dikembalikan secara bergantian. Namun, operasi seperti menempatkan pesanan pada bot akan menyebabkan keterlambatan, yang dapat mengakibatkan akumulasi data. Untuk informasi seperti push eksekusi perdagangan, push akun, dan push interpolasi kedalaman, kita membutuhkan data riwayat. Untuk data pasar kutipan, dalam kebanyakan kasus, kita hanya peduli dengan data terbaru, bukan data riwayat.
Jikaread()
menambahkan tidak ada parameter, itu akan mengembalikan data tertua, dan blok sampai kembali ketika tidak ada data.client.read(-2)
untuk mengembalikan data terbaru segera, tetapi ketika tidak ada data, itu akan mengembalikan nol, yang perlu dinilai sebelum referensi.
Tergantung pada cara menangani data cache lama dan apakah itu diblokir ketika tidak ada data,
Dalam hal ini jelas bahwa 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
}
}
Bagian pemrosesan ini lebih merepotkan, karena data push dapat terganggu, atau penundaan push sangat lama. Bahkan jika detak jantung dapat diterima, itu tidak berarti data masih didorong. Anda dapat mengatur interval acara; jika tidak ada pembaruan yang diterima setelah interval, sambung kembali; yang terbaik adalah membandingkan hasil yang dikembalikan oleh
Untuk data push telah digunakan, program secara alami akan ditulis sebagai event-triggered; perhatikan frekuensi data push, karena permintaan frekuensi tinggi akan menyebabkan diblokir; umumnya Anda dapat 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)
}
}
Metode koneksi, metode transmisi data, konten langganan dan format data websocket pada setiap platform sering berbeda, sehingga platform tidak mengkapsulkannya dan perlu menggunakan fungsi Dial untuk terhubung sendiri.
PS: Meskipun beberapa platform tidak menyediakan kutipan websocket, pada kenyataannya, ketika Anda masuk ke situs web untuk menggunakan fungsi debugging, Anda akan menemukan bahwa mereka semua menggunakan websocket push.
JavaScript dapat mewujudkan konvergensi oleh fungsi Go, dan Python dapat menggunakan perpustakaan multithread yang sesuai.
Saat realisasi strategi kuantitatif, eksekusi bersamaan dapat mengurangi keterlambatan waktu dan meningkatkan efisiensi.
var depthA = exchanges[0].GetDepth()
var depthB = exchanges[1].GetDepth()
Ketika permintaan API istirahat tertunda, misalnya waktu penundaan adalah 100 milidetik, maka waktu untuk mendapatkan kedalaman dua kali sebenarnya berbeda; jika lebih banyak akses diperlukan, masalah penundaan akan lebih jelas, yang akan mempengaruhi pelaksanaan strategi.
Karena JavaScript tidak memiliki multithread, lapisan bawah mengkapsulkan fungsi Go untuk memecahkan masalah ini. fungsi Go dapat digunakan untuk API yang membutuhkan akses jaringan, sepertiGetDepth
, GetAccount
dan sebagainya.IO
juga didukung, seperti:exchange.Go("IO", "api", "POST", "/api/v1/contract_batchorder", "orders_data=" + JSON.stringify(orders))
, tapi karena mekanisme desain, itu lebih membosankan untuk menerapkan.
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 kasus yang paling sederhana, menulis strategi dengan cara ini baik-baik saja. Tetapi perhatikan bahwa prosesnya diulang setiap kali strategi loop, dan variabel perantara a dan b sebenarnya hanya sementara bantu. Jika kita memiliki banyak tugas serentak, kita perlu tambahan mencatat korespondensi antara a dan depthA, b dan depthB. Ketika tugas serentak kita tidak pasti, situasinya lebih rumit. Oleh karena itu, kita berharap untuk mewujudkan fungsi: ketika menulis Go fungsi serentak, mengikat variabel pada saat yang sama; ketika hasil berjalan serentak kembali, nilai hasil secara otomatis diberikan kepada variabel, sehingga menghilangkan kebutuhan untuk membuat variabel perantara dan program lebih ringkas. Implementasi spesifik adalah sebagai berikut:
function G(t, ctx, f) {
return {run:function(){
f(t.wait(1000), ctx)
}}
}
Kami mendefinisikan fungsi G, di mana parameter
Pada saat ini, kerangka kerja program secara keseluruhan dapat ditulis sebagai model, mirip 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)
}
}
Tampaknya hanya fungsi sederhana yang telah diimplementasikan dalam operasi di atas. Sebenarnya, itu telah sangat menyederhanakan kompleksitas kode. Kita hanya perlu peduli tentang tugas apa yang perlu dihasilkan program, dan program
Dalam tutorial dasar, perpustakaan kelas gambar direkomendasikan dalam pengenalan gambar, yang dapat memenuhi kebutuhan dalam kebanyakan kasus.
Parameter internal dariChart({…})
adalah objek dari HighStock dan HighCharts, tetapi parameter tambahan__isStock
FMZ pada dasarnya mendukung modul dasar dari HighCharts dan HighStock, tetapi tidak mendukung modul tambahan.
Contoh khusus HighCharts:https://www.highcharts.com/demo; Contoh HighStock:https://www.highcharts.com/stock/demo. Anda dapat merujuk pada kode dalam contoh-contoh itu, dan mentransplantasinya ke FMZ nyaman.
Anda dapat memanggil add ([series index ((seperti 0), data]) untuk menambahkan data ke dalam seri dengan indeks yang ditentukan. Panggilan reset (() untuk membersihkan data grafik; reset dapat mengambil parameter angka dan menentukan jumlah yang akan disimpan. Tampilan grafik ganda didukung, yang hanya perlu dilewati dalam parameter array selama konfigurasi, seperti: var chart = Chart (([{...}, {...}, {...}]). Misalnya, jika Chart1 memiliki dua seri, Chart2 memiliki satu seri, dan Chart3 memiliki satu seri, ketika memanggil add, ID seri 0 dan 1 ditentukan untuk mewakili data dari dua seri secara terpisah dalam Chart1 yang diperbarui; ID seri 2 ditentukan untuk mewakili data dari seri pertama dalam Chart2; ID seri 3 ditentukan untuk mewakili data pertama dari seri dalam Chart3.
Contoh spesifik:
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 tata letak grafik:https://www.fmz.com/strategy/136056
Alamat sumber terbuka khusus:https://github.com/fmzquant/backtest_python
Pemasangan
Masukkan perintah berikut di baris perintah:
pip install https://github.com/fmzquant/backtest_python/archive/master.zip
Contoh Sederhana
Tetapkan parameter backtest di awal kode strategi dalam bentuk komentar, dan rincian akan ditampilkan di tombol
'''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
Backtest
Untuk strategi lengkap membutuhkan loop tak terbatas, kesalahan EOF akan meningkat setelah backtest selesai; oleh karena itu, kita harus melakukan toleransi kesalahan 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) beralih sumber data backtest dan menggunakan data K-line kustom. Parameter
dalam array arr, format data dari 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 dapat diimpor ke
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")
}
Catatan: pastikan untuk mengimpor data kustom terlebih dahulu (yaitu, panggil fungsi exchange.SetData untuk mengatur data) selama inisialisasi. Periode data K-line kustom harus konsisten dengan periode K-line sublayer yang ditetapkan pada halaman backtest, yaitu: data K-line kustom; waktu K-line adalah 1 menit, jadi periode K-line sublayer yang ditetapkan dalam backtest juga harus ditetapkan menjadi 1 menit.
Jika API platform yang tidak didukung persis sama dengan platform yang didukung, kecuali alamat dasar, platform yang tidak didukung dapat didukung dengan beralih alamat dasar. Untuk lebih spesifik, pilih platform yang didukung saat menambahkan platform, tetapi isi API-KEY dari platform yang tidak didukung, dan gunakan IO untuk mengubah alamat dasar 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 didukung oleh FMZ, tetapi platform kami telah menyediakan metode akses protokol umum.
Secara sederhana, protokol umum adalah seperti perantara, proxy permintaan docker dan mengembalikan data, sesuai dengan standar yang sesuai. Kode protokol umum perlu diselesaikan sendiri. Menulis protokol umum sebenarnya berarti bahwa Anda dapat mengakses platform saja dan menyelesaikan strategi. FMZ resmi kadang-kadang merilis versi exe dari protokol umum platform. Protokol umum juga dapat dilakukan di Python, yang kemudian dapat dijalankan di docker sebagai bot biasa.
Pengenalan khusus protokol umum:https://www.fmz.com/bbs-topic/9120Contoh menulis protokol umum dalam Python:https://www.fmz.com/strategy/101399
Sama seperti berbagai operasi platform dapat diimplementasikan melalui API, situs web FMZ juga didasarkan pada API. Anda dapat mengajukan permohonan untuk API-KEY Anda sendiri dari situs web FMZ untuk mewujudkan fungsi, seperti
Karena ekstensibilitas kuat dari platform FMZ Quant, Anda dapat membuat platform kuantitatif Anda sendiri berdasarkan ekstensi API, memungkinkan pengguna Anda untuk menjalankan bot di platform Anda, dll. Referensi spesifik:https://www.fmz.com/bbs-topic/1697 .
Pasar perdagangan cryptocurrency telah menarik lebih banyak perhatian dari pedagang kuantitatif karena keunikannya. Faktanya, perdagangan program telah menjadi arus utama cryptocurrency, dan strategi seperti lindung nilai dan pembuatan pasar selalu aktif di pasar. Pemula dengan dasar pemrograman yang lemah ingin memasuki bidang baru ini, berhadapan dengan banyak platform dan mengubah API, penuh dengan kesulitan.www.fmz.com) saat ini komunitas kuantitatif cryptocurrency terbesar dan platform, telah membantu ribuan pemula di jalan untuk perdagangan kuantitatif selama lebih dari 4 tahun.
PromosiKursus Perdagangan Kuantitatif Cryptocurrency di NetEase Cloud Classroom. Masuk ke NetEase Cloud Classroom dan bagikan link kursus Anda (linknya memiliki ID kursus yang unik). Yang lain, yang mendaftar dan membeli kursus melalui tautan ini, akan membawa Anda 50% dari total sebagai komisi, yaitu 10 yuan. Ikuti akun publik WeChat
Konsumen yang mengklik tautan promosi, mendaftar dan mengisi ulang dalam waktu setengah tahun, akan menikmati kebijakan bahwa perusahaan kami akan memberikan potongan harga sesuai dengan jumlah yang efektif dalam urutan yang berlaku. Komisi akan dikembalikan ke akun promotor dalam bentuk poin. Pengguna dapat menukar poin ke saldo akun platform FMZ dengan rasio 10: 1, dan pengguna juga dapat menggunakan poin untuk menukar produk terkait FMZ Quant di masa depan. Tautan khusus untuk kegiatan:https://www.fmz.com/bbs-topic/3828
Situs web FMZ lengkap dapat dikerahkan ke server eksklusif perusahaan atau tim untuk kontrol lengkap dan kustomisasi fungsional. Situs web FMZ telah digunakan dan diuji oleh sekitar 100.000 pengguna, dan telah mencapai ketersediaan dan keamanan yang tinggi, yang dapat menghemat waktu untuk tim kuantitatif dan perusahaan. Versi perusahaan adalah untuk tim perdagangan kuantitatif berukuran sedang, penyedia layanan berjangka komoditas, dll. Silakan hubungi administrator untuk penawaran spesifik.
Sistem profesional, menyediakan likuiditas pasar dan manajemen dana untuk platform, mungkin merupakan sistem pembuatan pasar yang paling ditingkatkan di pasar.
Sistem perdagangan teknologi FMZ mengadopsi teknologi pencocokan memori, dan kecepatan pemrosesan pesanan setinggi 2 juta perdagangan per detik, yang dapat memastikan bahwa tidak akan ada penundaan atau lag dalam pemrosesan pesanan. Ini dapat menjaga operasi yang lancar dan stabil dari platform dengan lebih dari 20 juta pengguna online bersamaan. Kerangka sistem multi-lapisan dan multi-kluster memastikan keamanan, stabilitas dan ekstensibilitas sistem. Penyebaran fungsi dan pembaruan versi dapat dilakukan tanpa downtime, yang menjamin pengalaman operasi pengguna terminal maksimal. Saat ini, sistem dapat dialami di platform simulasi wex.app.