FMZ 量子プラットフォームの戦略書き方に関する上級チュートリアル

作者: リン・ハーンニナバダス, 作成日: 2022-03-22 09:00:57, 更新日: 2022-03-29 10:02:52

[TOC] このチュートリアルを学ぶ前に,あなたは勉強する必要がありますFMZ 量子プラットフォームから始めようそしてFMZ 量子プラットフォームの基本チュートリアル 戦略執筆プログラミング言語の習得ができるようになります基本的なチュートリアルでは最も一般的に使用される機能がカバーされていますが,導入されていない多くの機能と機能があり,このチュートリアルではカバーされません.それらを自分で理解するには,FMZプラットフォームのAPI文書をブラウズする必要があります.FMZ Quantプラットフォームは単なるツールです. このビデオでは,

プラットフォームの原始データへのアクセス

FMZ Quantプラットフォームは,サポートされているすべてのプラットフォームをカプセル化しています.統一性を維持するために,単一のプラットフォーム API のサポートはまだ完了していません.例えば,GetRecords は,K ライン数または開始時間を渡すことができますが,それは FMZ プラットフォームで固定されています.一部のプラットフォームはバッチオーダーをサポートしていますが,FMZ はそれをサポートしていません.公開インターフェース (市場コートなど) では,HttpQuery暗号化されたインターフェース (アカウント情報を含む) では,IO.特定の入力パラメータについては,対応するプラットフォーム API ドキュメントを参照してください. 前回のチュートリアルでは,Infoインターフェースがサポートされていない問題には 変化はありません

GetRawJSON を取得する

REST API で要求された原始コンテンツ (文字列) を返します. この文字列は拡張された情報を自分で解析するために使用できます.

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() 公開インターフェースにアクセス

公開インターフェースにアクセスするには,Js はHttpQueryPython は,以下のような関連パッケージを使用できます.urllibまたはrequests.

HttpQuery は GET メソッドをデフォルトで設定し,より多くの機能をサポートします.詳細については API 文書を参照してください.

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"))

Python の 要求 を 使う 例:

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()

暗号化されたインターフェースにアクセスするIO

API-KEY シグネチャーを必要とするインターフェースでは,IO 機能が使用され,ユーザーは入ってくるパラメータだけを気にする必要があり,特定の署名プロセスは,サブレイヤーによって完了します.

FMZプラットフォームは現在,BitMEXストップロスの注文をサポートしていません.以下の手順に従ってIOを通じて実行できます.

  • まず,BitMEX APIのインストラクションページを見つけます.https://www.bitmex.com/api/explorer/;
  • その場合は,BitMEXの注文アドレスを:https://www.bitmex.com/api/v1/order方法によってPOST; FMZ は既に内部でベースアドレスを指定しているので, /api/v1/order を入力するだけです.
  • 対応するパラメータ:symbol=XBTUSD&side=Buy&orderQty=1&stopPx=4000&ordType=Stop.

特定コード:

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"}))

さらに IO の例:https://www.fmz.com/bbs-topic/3683

Webソケットを使用

基本的には,すべての仮想通貨プラットフォームは,市場報定を送信するためにwebsocketをサポートし,一部のプラットフォームはアカウント情報を更新するためにwebsocketをサポートしている.レストAPIと比較して,websocketは一般的に低レイテンシー,高周波,プラットフォームレストAPIの頻度によって制限されないなどの利点があります.デメリットとしては,処理が直感的でない中断問題があります.

この記事では,主にJavaScript言語を使用する方法と,FMZ Quantプラットフォームで接続するためにプラットフォームによってカプセル化されたDial関数をどのように使用するかについて紹介します.特定の指示とパラメータは文書にあります.Dialを検索できます.さまざまな機能を実現するために,Dial関数は数回更新されています.この記事では,wssに基づいたイベント駆動戦略,および複数のプラットフォームを接続する問題を紹介します.PythonはDial関数または対応するライブラリも使用できます.

Webソケット接続

一般的には Websocket で直接接続します.例えば,Binance Tricker push を取得するには,

var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")

復元されたデータが圧縮形式にある場合,接続時に仕様を指定する必要があります. compressは圧縮形式を指し, modeは復元されたデータが圧縮する必要があることを表します.例えば,OKEXに接続する場合:

var client = Dial("wss://real.okex.com:10441/websocket?compress=true|compress=gzip_raw&mode=recv")

ダイアル機能は,元となるGolangによって実行される再接続をサポートします.検出された接続が故障した場合,再接続されます.既にURLにあるリクエストデータ,例えばBinanceの例のように,非常に便利で推奨されます.サブスクリプションメッセージを送信する必要がある人は,再接続メカニズムを自分で維持することができます.

var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr|reconnect=true")

WSSのメッセージへの購読には,いくつかのプラットフォームのリクエストがURLに表示され,一部のユーザーは購読したチャンネルを自分で送信する必要があります. 例えば,coinbase:

client = Dial("wss://ws-feed.pro.coinbase.com", 60)
client.write('{"type": "subscribe","product_ids": ["BTC-USD"],"channels": ["ticker","heartbeat"]}')

2.暗号化されたインターフェイス接続

Webソケットは,通常,市場報價を読み取るのに使用されますが,注文とアカウントプッシュも利用できます.そのような暗号化されたデータのプッシュは,時には長い遅延があり,注意して使用する必要があります.暗号化方法はより複雑なので,参考にいくつかの例があります. 戦略パラメータとして設定できる AccessKey だけが必要であることを注意してください. SecretKey が必要であれば,セキュリティを確保するために交換によって暗黙に呼び出されます.HMAC ((() 機能.

    //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)
        }
    }

Webソケット読み込み

一般的には,無限のループで連続的に読み取れます.コードは以下の通りです:

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 
    }
}

Wssデータプッシュスピードは非常に速い. Golangのサブレイヤーはキュー内のすべてのデータをキャッシュし,プログラムが呼び出せば,データは順番に返されます.しかし,ボットに注文を出すなどの操作は遅延を引き起こすため,データの蓄積につながる可能性があります.取引実行プッシュ,アカウントプッシュ,深度インターポレーションプッシュなどの情報には,履歴データが必要です. コート市場データについては,ほとんどの場合,我々は履歴データではなく最新のデータだけを気にします.

もしread()最新のデータを使用できます. 古いデータと新しいデータを使用します.client.read(-2)最新のデータを即座に返却しますが,データが存在しない場合は null を返します.これは参照前に判断する必要があります.

古いキャッシュされたデータを処理する方法や,データがないときにブロックされるかどうかに依存して,下記の表で示されているように,readには異なるパラメータがあります.これは複雑に見えますが,プログラムをより柔軟にします.img

4.Webソケットで複数のプラットフォームに接続

この場合は,単に"読み込み"を用いると,プログラムでは機能しないことが明らかです.なぜなら,あるプラットフォームは待機しているメッセージをブロックし,別のプラットフォームは新しいメッセージがあるとしても受信しないからです.一般的な処理方法は:

    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
        }
    }

5. 断線と再接続の問題

プッシュデータは中断される可能性があるため,またはプッシュ遅延が非常に長いため,処理のこの部分はより面倒です.心臓の鼓動が受信されても,データがまだプッシュされていることを意味しません.イベント間隔を設定できます.間隔後に更新が受信されない場合は,再接続します.データが正確かどうかを確認するために,期間後にrestによって返された結果を比較することが最善です.バイナンス特殊の場合,自動的に再接続を直接設定できます.

WebSocket の 一般 プログラム フレームワーク を 使用 する

プッシュデータが使用されているため,プログラムは自然にイベントトリガーで記述されます. プッシュデータの周波数に注意してください. 高周波のリクエストがブロックされるので,一般的に,次のように書くことができます:

    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)
        }
    }

7.Conclusion

接続方法,データ送信方法,サブスクリプションコンテンツ,各プラットフォームのウェブソケットのデータフォーマットはしばしば異なるため,プラットフォームはそれをカプセル化せず,自己接続のためにダイヤル機能を使用する必要があります.この記事は基本的にいくつかの基本的な注意事項をカバーしています.質問がある場合は,気軽に尋ねてください.

PS: Webソケット引用文は提供されていないプラットフォームもありますが,デバッグ機能を使用するためにWebサイトにログインすると,すべて Webソケットプッシュを使用していることがわかります. 調べた後に,一部のサブスクリプションフォーマットとリターンフォーマットが暗号化されていることがわかります.

マルチスレッド同期

JavaScript は Go 関数によるコンクリートを実現し, Python は対応するマルチスレッドライブラリを使用できます.

定量戦略の実現中に,同時実行は時間遅れを軽減し効率を向上させることができます.ヘジング戦略ボットを例に挙げましょう.それは2つのコインの深さを得なければなりません.順番で実行されたコードは以下のように表示されます.

var depthA = exchanges[0].GetDepth()
var depthB = exchanges[1].GetDepth()

休憩APIのリクエストが遅れている場合,例えば遅延時間は100ミリ秒である場合,深さを2回取得する時間は実際には異なります.より多くのアクセスが必要であれば,遅延問題はより明らかになり,戦略の実行に影響します.

JavaScript にはマルチスレッドがないため,下層はこの問題を解決するためにGo関数をカプセル化している.Go関数は,ネットワークアクセスを必要とする API に使用できます.GetDepth, GetAccountそしてこれからもIOまた,以下のような支援も行われています.exchange.Go("IO", "api", "POST", "/api/v1/contract_batchorder", "orders_data=" + JSON.stringify(orders))設計メカニズムにより,実装はより退屈です.

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()

戦略を書き出すのは,最も単純な場合でも大丈夫です.しかし,このプロセスは,戦略ループが繰り返されるたびに繰り返され,中間変数 a と b は実際には一時的に補助的なものだけです.当時は同時作業がたくさんある場合,さらに a と depthA, b と depthB の間の対応を記録する必要があります.当時の作業が不確実である場合,状況はより複雑になります.したがって,関数を実現することを希望します. Go 関数を同時書き込むとき,同時に変数を結合します.同時実行結果が返されるとき,結果値は自動的に変数に割り当てられ,それによって中間変数とプログラムをより簡潔にする必要性をなくします.具体的な実装は以下のとおりです:

function G(t, ctx, f) {
    return {run:function(){
        f(t.wait(1000), ctx)
    }}
}

実行する Go 関数,記録プログラムコンテキストの関数,特定の値を代入する関数です. この関数の効果は後でご覧いただけます.

この時点で,全体的なプログラムフレームワークはモデルとして記述できます. 生産者-消費者モデルに似ている (いくつかの違いがあります),生産者は継続的にタスクを送信し,消費者は同時に実行します. 次のコードはデモのみであり,プログラム実行ロジックを含まない.

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)
    }
}

上記の操作では単純な機能のみが実装されているようです.実際,それはコードの複雑さを大幅に簡素化しました.プログラムが生成する必要があるタスクについてのみ気にする必要があり,worker() プログラムは自動的にそれらを同時実行し,対応した結果を返します.柔軟性は大幅に改善されました.

図表機能による図解

基本チュートリアルでは,図解の導入に図解クラスライブラリが推奨されており,ほとんどの場合ニーズを満たすことができます.さらなるカスタマイゼーションが必要な場合は,直接チャートオブジェクトを操作できます.

内部パラメータChart({…})は HighStock と HighCharts のオブジェクトですが,追加のパラメータです.__isStockFMZは,基本的にはHighChartsとHighStockの基本モジュールをサポートしているが,追加のモジュールをサポートしていない.

HighChartsの具体的な例はhttps://www.highcharts.com/demo■ハイストック例:https://www.highcharts.com/stock/demoFMZに簡単に移植できます. 簡単にFMZに移植することができます.

設定中に配列パラメータを通過するだけでサポートされる複数のチャート表示,例えば: var chart = Chart (([{...}, {...}, {...}).例えば,Chart1が2つのシリーズを持つ場合,Chart2は1つのシリーズを持ち,Chart3は1つのシリーズを持ち,addを呼び出すとき,シリーズID0と1は更新されたチャート1の2つのシリーズのデータを別々に表現するために指定されている.シリーズID2はチャート2の最初のシリーズのデータを表現するために指定されている.シリーズID3はチャート3の最初のシリーズのデータを表現するために指定されている.

具体例として

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);
    }
}

図面のレイアウトを使用する例:https://www.fmz.com/strategy/136056

先進的なバックテスト

Python ロカルのバックテスト

特定のオープンソースアドレス:https://github.com/fmzquant/backtest_python

設置

次のコマンドをコマンド行に入力します.

pip install https://github.com/fmzquant/backtest_python/archive/master.zip

シンプル な 例

バックテストのパラメータをコメント形式で戦略コードの初めに設定すると,詳細はFMZウェブサイトの"戦略編集"ページの"設定を保存する"ボタンの上で表示されます.

'''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

バックテスト

完全な戦略には無限のループが必要なので,EOFエラーはバックテストが終了した後で上昇します.したがって,私たちは誤差耐性をよくする必要があります.

# !/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) はバックテストデータソースを切り替えてカスタムK線データを使用します.パラメータarrは配列で,その要素はK線バーデータ (すなわち,一時的にJavaScriptバックテストのみをサポートするK線データ配列) です.

arr の配列では,単一の要素のデータ形式:

[
    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 
]

データソースは テンプレートにインポートできます.

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")
}

注:初期化中に最初にカスタムデータをインポートすることを確認してください (すなわち,データを設定するために exchange.SetData関数を呼び出す).カスタム K ラインデータ期間はバックテストページに設定されたサブレイヤ K ライン期間,すなわち:カスタム K ラインデータと一致する必要があります.

FMZ がサポートしていないプラットフォームを使用する

サポートされていないプラットフォームのAPIがサポートされているプラットフォームとまったく同じである場合,ベースアドレスを除く場合,サポートされていないプラットフォームはベースアドレスを切り替えてサポートできます.具体的には,プラットフォームを追加するときにサポートされているプラットフォームを選択しますが,サポートされていないプラットフォームのAPI-KEYを入力し,戦略でベースアドレスを切り替えるためにIOを使用します.

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

FMZはすべてのプラットフォームをサポートしていませんが,当社のプラットフォームは一般プロトコルのアクセス方法を提供しています. 具体的な原則は:

  • プラットフォームにアクセスするためのコードを書くと プログラムは Web サービスを作成します
  • FMZにプラットフォームを追加すると Web サービスのアドレスとポートを指定します
  • ドッカーが一般プロトコルのプラットフォームボットを実行しているとき,戦略のAPIアクセスリクエストは一般プロトコルに送られます.
  • 一般プロトコルはリクエストでプラットフォームにアクセスし,ドッカーに結果を返します.

一般プロトコルは,単純に言えば,ドーカーの要求をプロキシして,対応する標準に従ってデータを返却する仲介業者のようなものです. 一般プロトコルのコードは自分で完了する必要があります. 一般プロトコルの書き込みは,実際には,プラットフォームのみにアクセスして戦略を完了することができます. FMZ 公式は時々プラットフォームの一般プロトコルの exe バージョンをリリースします. 一般プロトコルはPythonでも行えます. その後,通常のボットとしてドーカーの上で実行できます.

一般プロトコルの特別導入:https://www.fmz.com/bbs-topic/9120Python での一般プロトコルの記述の例:https://www.fmz.com/strategy/101399

自分の定量的なプラットフォームを作成する

プラットフォームのさまざまな操作がAPIを通じて実装されるように,FMZウェブサイトもAPIに基づいています. 機能を実現するために,FMZウェブサイトの独自のAPI-KEYを申請できます.例えば,create,restart,DeleteRobot,GetRobotList GetRobotLogsなど.詳細についてはAPI文書のFMZプラットフォームのAPI拡張子を参照してください.

FMZ Quant プラットフォームの強力な拡張性により,API エクステンションに基づいて独自の定量プラットフォームを作成し,ユーザーにプラットフォーム上でボットを実行できるようにすることができます.https://www.fmz.com/bbs-topic/1697 .

FMZのパートナーになる

NetEase教室の推進

仮想通貨取引市場は,その特異性により定量的なトレーダーからますます注目を集めている.実際には,プログラム取引は仮想通貨のメインストリームになり,ヘッジやマーケットメーキングなどの戦略は常に市場で活発です. プログラミング基盤が弱い初心者は,多くのプラットフォームと変化するAPIに直面し,困難に満ちたこの新しい分野に入りたいと考えています. FMZ Quant Platform, (元BotVs,www.fmz.com現在最大の暗号通貨の定量コミュニティとプラットフォームで,数値取引への道を4年以上にわたって何千人もの初心者に助けています. NetEaseのコースを受講するには,わずか20元で,コースは完全に初心者向けです.

促進するNetEase Cloud Classroom での暗号通貨量的な取引コース. NetEase Cloud Classroom にログインしてコースリンクをシェアする (リンクにはユニークなコースIDがあります). このリンクを通じてコースを登録して購入する他のユーザーは,合計の50%を佣金として,すなわち10元で受け取ります. 現金を引き出すためにNetEase Cloud Classroom Premium Course PromotionのWeChat 公開アカウントをフォローしてください.また, Weibo または QQ グループでコースをプロモートするために他の人を招待することもできます.

アフィリエイト

広告リンクをクリックし,登録して半年以内にリチャージする消費者は,当社が有効な順序で有効金額に応じてリバウンドする方針を享受します. 委員会はポイントの形でプロモーターの口座に戻されます. ユーザーはポイントをFMZプラットフォームの口座残高に10:1の比率で交換することができ,ユーザーは将来的にFMZ Quantの関連製品を交換するためにポイントを使用することもできます. 活動のための特定のリンク:https://www.fmz.com/bbs-topic/3828

FMZ 企業向け量子プラットフォーム

FMZのウェブサイトは,完全な制御と機能的カスタマイゼーションのために企業またはチームの専用サーバーに展開できます. FMZのウェブサイトは約10万人のユーザーによって使用およびテストされており,定量チームおよび企業にとって時間を節約できる高可用性およびセキュリティを達成しました. 企業版は中規模の定量取引チーム,商品先物サービスプロバイダーなど向けです. 特定の kota メントのために管理者に連絡してください.

市場作るシステム

プロフェッショナル・システムは,プラットフォームの市場流動性と資金管理を提供しており,市場で最も改良されたマーケットメーキングシステムである可能性があります.多くのプラットフォームとチームによって広く使用されています.

プラットフォーム・スキーム

FMZ技術取引システムはメモリマッチング技術を採用し,注文処理速度は秒速200万取引まで高く,注文処理に遅延や遅れがないことを保証することができます. 同時オンラインユーザー2000万人以上のプラットフォームのスムーズかつ安定した動作を維持できます. 多層および多クラスターシステムフレームワークはシステムのセキュリティ,安定性および拡張性を保証します. 機能展開およびバージョン更新はダウンタイムなしで実行することができ,ターミナルユーザーのオペレーティング体験を最大限に保証します. 現在,システムはwex.appシミュレーションプラットフォームで経験することができます.


もっと