3
フォロー
1444
フォロワー

FMZ 定量プラットフォーム戦略ライティング上級チュートリアル

作成日:: 2019-08-19 15:54:35, 更新日:: 2021-06-08 16:14:57
comments   8
hits   32175

[TOC] このトークを学ぶ前に,まず学ぶ必要があります.FMZの発明者による量化プラットフォームの導入そしてFMZ 量化プラットフォームの策略 初期チュートリアル作成プログラミング言語の熟練者初級チュートリアルでは,最もよく使用される機能が扱われていますが,このチュートリアルではカバーされない多くの機能や機能があります. プラットフォームのAPIドキュメントを閲覧して自分で理解する必要があります.FMZのプラットフォームは単なるツールに過ぎません.

エクスチェンジの原始データへのアクセス

FMZプラットフォームは,支持されているすべての取引所をパッケージ化しており,統一性を保つために,個々の取引所APIのサポートは不完全である.例えば,K線を取得すると,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は,Pythonのパッケージを,Pythonのパッケージと,Pythonのパッケージと,Pythonのパッケージと,Pythonのパッケージと,Pythonのパッケージと,Pythonのパッケージと,Pythonのパッケージと,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方法としてPOSTFMZは内部で root アドレスを指定しているので”,/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")
//也可以直接传入对象
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

WebSocketを使用する

基本的にはすべての仮想通貨取引所がwebsocketの送付対応で,一部の取引所ではwebsocketの更新アカウント情報に対応している.rest APIと比較して,websocketは一般的に遅延が低く,頻度が高く,プラットフォームrest APIの頻度制限などに左右されない.欠点は,中断の問題があり,処理は直感的ではない.

この記事では,主にFMZの発明者による量化プラットフォーム,JavaScript言語を使用し,プラットフォームが封入したDial関数を使用して接続する.詳細とパラメータはドキュメントに記載されており,Dialを検索します.様々な機能を実現するために,Dial関数は数回更新されています.この記事は,この点をカバーし,wssベースのイベント駆動の策略,および複数の取引所を接続する問題について説明します.

1. ウェブソケット接続

コインのセキュリティティッカーの推送など,一般的には直接接続できます.

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

Dial関数は再接続をサポートし,底層のGo言語で完了し,検出された接続断絶会再接続,リクエストデータコンテンツが既にurlにある場合,例えば今度のBinanceの例のように,便利で,使用が推奨されます. メッセージを送信する必要がある場合,再接続メカニズムを自分で維持できます.

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

コインベース (coinbase) のようなチャンネルは,自己登録の必要性がある:

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

2. 密閉口の接続

一般的にはwebsocketの読み取りが用いられるが,注文やアカウントの推送も利用できる.この種の暗号化データの推送は時に大きな遅れがあるため,注意が必要である.暗号化方法が複雑であるため,いくつかの例を参考に挙げている.AccessKeyのみが必要であり,SecretKeyが必要な場合は,Exchange.HMAC) の関数 ((の暗黙呼び出しでセキュリティを保証する) のように,ポリシーパラメータとして設定できることに注意する.

    //火币期货推送例子
    var ACCESSKEYID = '你的火币账户的accesskey'
    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} }") //去掉}}之间的多余空格
    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}))
        }
    }
    
    //币安推送例子,注意需要定时更新listenKey
    var APIKEY = '你的币安accesskey'
    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()
    }

    //BitMEX推送例子
    var APIKEY = "你的Bitmex API ID"
    var expires = parseInt(Date.now() / 1000) + 10
    var signature = exchange.HMAC("sha256", "hex", "GET/realtime" + expires, "{{secretkey} }")//secretkey在执行时自动替换,不用填写
    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)
        }
    }

3. websocket の読み取り

このコードは,通常,デッドループで読み取れます.

function main() {
    var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr");
    while (true) {
        var msg = client.read()
        var data = JSON.parse(msg) //把json字符串解析为可引用的object
// 处理data数据
    }
}

wssのデータプッシュは高速で,Goの底層はすべてのデータをキューにキャッシュして,等プログラムがreadを呼び出すと,次々に返される。そして,リールディスクの注文などの操作は,遅延をもたらし,データの蓄積を引き起こす可能性がある。取引プッシュ,アカウントプッシュ,深度挿入値プッシュなどの情報には,歴史データが必要であり,実態データについては,ほとんどの場合,最新のデータだけを気にせず,歴史データに関心を持たない。

read()パラメータが加えられなければ,最も古いデータが返され,データがない場合は返されるまでブロックされます. 最新のデータが必要な場合は,client.read(-2)すぐ最新のデータに戻すが,もうデータがないとnullに戻す,判断して再引用する.

read は,キャッシュされた古いデータをどのように扱うか,また,データがないときにブロックされるかどうかによって,異なるパラメータを持つ.具体的には,以下の図のように,複雑に見えますが,プログラムをより柔軟にします. FMZ 定量プラットフォーム戦略ライティング上級チュートリアル

4. 複数の取引所のWebSocketを接続する

このような場合,単純にread () を使うことは明らかにできない,なぜなら,ある取引所が待機しているメッセージをブロックし,その間,他の取引所が新しいメッセージがあったとしても受信できないからです.一般的処理方法は:

    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) // 参数-1代表无数据立即返回null,不会阻塞到有数据返回
            var msgCoinbase = coinbase.read(-1)
            if(msgBinance){
                // 此时币安有数据返回
            }
            if(msgCoinbase){
                // 此时coinbase有数据返回
            }
            Sleep(1) // 可以休眠1ms
        }
    }

5. 断線再接続問題

この部分では処理が面倒であるため,推送データは中断したり,推送遅延が非常に高く,ハートビットを受信してもデータが推送されているわけではない.イベント間隔を設定し,更新が受信されていない間隔を超えた場合は再接続し,しばらくの間,restと返された結果と比較してデータの正確さを確認する.この特殊なケースでは,直接自動再接続を設定できます.

6. websocketを使用する一般的なプログラムフレームワーク

推送データを使用しているため,プログラムも自然にイベントドライブに書き込む必要があります. 推送データの頻度に注意し,過度の要求によって封鎖されないように注意してください. 一般的に次のように書き込むことができます.

    var tradeTime = Date.now()
    var accountTime = Date.now()
    function trade(data){
        if(Date.now() - tradeTime > 2000){//这里即限制了2s内只交易一次
            tradeTime = Date.now()
            //交易逻辑
        }
    }
    function GetAccount(){
        if(Date.now() - accountTime > 5000){//这里即限制了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)
        }
    }

7. 結論

各取引所のwebsocketの接続方法,データ送信方法,購読可能なコンテンツ,データフォーマットは,しばしば異なっています.したがって,プラットフォームはパッケージ化されず,ダイアル関数を使用して自主接続する必要があります.この文章は,基本的にはいくつかの基本的な注意事項をカバーしています.もし疑問があれば,質問をお願いします.

PS.一部の取引所はWebSocketの行方を提供していないが,実際にWebSocketの設定機能を利用したサイトにアクセスすると,WebSocketの推送が使用されていることがわかります.調べてみると,サブスクリプションフォーマットと返却フォーマットが見られます.

複数のスレッドを並行して

JavaScriptはGo関数で並列化を実現し,Pythonは対応する多線型ライブラリを使用する.

量化戦略の実装では,多くの場合,並列実行は遅延の提昇効率を低下させることができる.例えば,ヘッジ戦略の实体ディスクでは,二コインの深さを取得する必要があります.順番で実行されるコードは以下の通りです.

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

REST 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() //调用wait方法等待返回异步获取depth结果 
var depthB = b.wait()

最も単純なケースでは、このようにポリシーを記述しても問題はありません。ただし、このプロセスは戦略がループするたびに繰り返す必要があり、中間変数 a と b は実際には一時的な補助にすぎないことに注意してください。同時実行タスクが多数ある場合は、a と depthA、b と depthB の対応を記録する必要があります。同時実行タスクが不確実な場合、状況はさらに複雑になります。そこで、Goの並行処理を書くときに、同時に変数をバインドし、並行実行の結果が返されたときに、その結​​果が自動的に変数に割り当てられるようにする関数を実装したい。これにより、中間変数がなくなり、プログラムがよりシンプルになる。簡潔。具体的な実装は以下のとおりです。

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

G 関数を定義します。ここで、パラメーター t は実行される Go 関数、ctx はプログラム コンテキスト、f は特定の割り当てのための関数です。この機能が実際にどのように動作するかは、後ほど説明します。

この時点で、全体的なプログラム フレームワークは、プロデューサーが継続的にタスクを発行し、コンシューマーがそれらを同時に実行する「プロデューサー - コンシューマー」モデルとして記述できます (いくつかの違いがあります)。次のコードはデモンストレーションのみを目的としており、プログラムには関係ありません。ロジックを実行します。

var Info = [{depth:null, account:null}, {depth:null, account:null}] //加入我们需要获取两个交易所的深度和账户,跟多的信息也可以放入,如订单Id,状态等。
var tasks = [ ] //全局的任务列表

function produce(){ //下发各种并发任务
  //这里省略了任务产生的逻辑,仅为演示
  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 //这里的v就是并发Go函数wait()的返回值,可以仔细体会下
                }))
    }
    _.each(jobs, function(t){
            t.run() //在这里并发执行所有任务
        })
    tasks = []
}
function main() {
    while(true){
        produce()         // 发出交易指令
        worker()        // 并发执行
        Sleep(1000)
    }
}

多くのステップを経て単純な関数を実装しただけのように見えますが、実際にはコードの複雑さが大幅に簡素化されています。プログラムが生成する必要のあるタスクとワーカー( ) プログラムはそれらを自動的に同時に実行し、対応する結果を返します。柔軟性が大幅に向上しました。

グラフのグラフ

初級チュートリアル 図図は,図図類のリポートとして推奨され,ほとんどの場合,必要に応じて対応する.さらにカスタマイズする必要がある場合は,Chartオブジェクトを直接操作することができます.

Chart({…})内部パラメータはHighStockとHighChartsのオブジェクトで,追加のパラメータが追加されています.__isStockHighStockであるかどうかを区別する.HighStockは時間序列の図に注目するので,よりよく使用される.FMZはHighChartsとHighStockの基本的なモジュールを基本的にはサポートするが,追加のモジュールはサポートしない.

HighChartsの具体的な例はhttps://www.highcharts.com/demo;HighStockの例はhttps://www.highcharts.com/stock/demo 。これらの例のコードを参考にして,FMZに簡単に移植できます。

add ((() を呼び出すことができます.[series インデックス ((例えば0),データ)) は,指定されたインデックスのseriesにデータを追加し,reset () を呼び出し,空のグラフデータで,resetは,数字のパラメータを持って,保留された条数を指定できます.複数のグラフを表示するサポートがあり,配置する際には,アーレストのパラメータを入力するだけです.例えば: var chart = Chart ()[{…}, {…}, {…}]),例えばグラフ1に2つのシリーズがあり,グラフ2に1つのシリーズがあり,グラフ3に1つのシリーズがあり,addで指定する0と1のシーレッジIDはグラフ1の2つのシリーズのデータを更新する,addで指定する2のシーレッジIDはグラフ2の1番目のシリーズのデータを表示し,指定する3のシーレッジIDはグラフ3の1番目のシリーズのデータを表示する.

具体例として:

var chart = { // 这个 chart 在JS 语言中 是对象, 在使用Chart 函数之前我们需要声明一个配置图表的对象变量chart。
    __isStock: true,                                    // 标记是否为一般图表,有兴趣的可以改成 false 运行看看。
    tooltip: {xDateFormat: '%Y-%m-%d %H:%M:%S, %A'},    // 缩放工具
    title : { text : '差价分析图'},                       // 标题
    rangeSelector: {                                    // 选择范围
        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'},                         // 坐标轴横轴 即:x轴, 当前设置的类型是 :时间
    yAxis : {                                           // 坐标轴纵轴 即:y轴, 默认数值随数据大小调整。
        title: {text: '差价'},                           // 标题
        opposite: false,                                // 是否启用右边纵轴
    },
    series : [                                          // 数据系列,该属性保存的是 各个 数据系列(线, K线图, 标签等..)
        {name : "line1", id : "线1,buy1Price", data : []},  // 索引为0, data 数组内存放的是该索引系列的 数据
        {name : "line2", id : "线2,lastPrice", dashStyle : 'shortdash', data : []}, // 索引为1,设置了dashStyle : 'shortdash' 即:设置 虚线。
    ]
};
function main(){
    var ObjChart = Chart(chart);  // 调用 Chart 函数,初始化 图表。
    ObjChart.reset();             // 清空
    while(true){
        var nowTime = new Date().getTime();   // 获取本次轮询的 时间戳,  即一个 毫秒 的时间戳。用来确定写入到图表的X轴的位置。
        var ticker = _C(exchange.GetTicker);  // 获取行情数据
        var buy1Price = ticker.Buy;           // 从行情数据的返回值取得 买一价
        var lastPrice = ticker.Last + 1;      // 取得最后成交价,为了2条线不重合在一起 ,我们加1
        ObjChart.add([0, [nowTime, buy1Price]]); // 用时间戳作为X值, 买一价 作为Y值 传入 索引0 的数据序列。
        ObjChart.add([1, [nowTime, lastPrice]]); // 同上。
        Sleep(2000);
    }
}

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__

# ------------------------------ 策略部分开始 --------------------------

print exchange.GetAccount()     # 调用一些接口,打印其返回值。
print exchange.GetTicker()

def adjustFloat(v):             # 策略中自定义的函数
    v = math.floor(v * 1000)
    return v / 1000

def onTick():
    Log("onTick")
    # 具体的策略代码


def main():
    InitAccount = GetAccount()
    while True:
        onTick()
        Sleep(1000)

# ------------------------------ 策略部分结束 --------------------------

try:
    main()                     # 回测结束时会 raise EOFError() 抛出异常,来停止回测的循环。所以要对这个异常处理,在检测到抛出的异常后调用 task.Join() 打印回测结果。
except:
    print task.Join()         

カスタム・フィットバック

exchange.SetData(arr),回測データソースを切り替え,カスタムされたK線データを使用する.参数 arr ,は,K線柱データ ((すなわち:K線データアレイ,暫くJavaScript回測のみをサポートする)) の要素である.

arr 配列では,単一の要素のデータフォーマット:

[
    1530460800,    // time     时间戳
    2841.5795,     // open     开盘价
    2845.6801,     // high     最高价
    2756.815,      // low      最低价
    2775.557,      // close    收盘价
    137035034      // volume   成交量
]

データソースは, テンプレート クラス 倉庫にインポートできます.

function init() {                                                          // 模板中的 init 初始化函数会在加载模板时,首先执行,确保 exchange.SetData(arr) 函数先执行,初始化,设置数据给回测系统。
    var arr = [                                                            // 回测的时候需要使用的K线数据
        [1530460800,2841.5795,2845.6801,2756.815,2775.557,137035034],      // 时间最早的一根 K线柱 数据
        ... ,                                                              // K线数据太长,用 ... 表示,数据此处省略。
        [1542556800,2681.8988,2703.5116,2674.1781,2703.5116,231662827]     // 时间最近的一根 K线柱 数据
    ]
    exchange.SetData(arr)                                                  // 导入上述 自定义的数据
    Log("导入数据成功")
}

注意:初期化時に必ず,まずカスタムデータを輸入する ([exchange.SetData関数設定データ]をコールする),カスタムK線データ周期は,反測ページで設定した底層K線周期と一致しなければならない.すなわち:カスタムK線データ,一本のK線時間は1分,反測で設定した底層K線周期も1分に設定する.

FMZでサポートされていない取引所

サポートされていない取引所とサポートされている取引所のAPIがまったく同じで,ベースアドレスは異なる場合,ベースアドレスを切り替えることでサポートすることができます. 取引所を追加する際にサポートされている取引所を選択しますが,API-KEYを記入しないサポートされていない取引所,戦略でIOでベースアドレスを切り替えます. 例えば:

exchange.IO("base", "http://api.huobi.pro") 
//http://api.huobi.pro为为支持交易所API基地址,注意不用添加/api/v3之类的,会自动补全

FMZは,すべての取引所がサポートしているわけではありませんが,このプラットフォームは,一般的な協定へのアクセスを提供しています.

  • プログラムがネットワークサービスを作成します.
  • FMZプラットフォームで取引所を追加し,ネットワークサービスのアドレスとポートを指定します.
  • 托管者が通用協定の取引所の实体を実行すると,ポリシー内のAPI アクセスが通用協定に送信されます.
  • 一般協定は,要求に応じて取引所にアクセスし,結果を托管者に返します.

簡潔に言えば,GPRは,対応する標準に従って托管者の要求を代理し,データを返還する仲介者と同等である.GPRのコードは,自分で完成させ,GPRを書き出すことは,実際に,あなたが個別に取引所にアクセスして,戦略を完了することを意味する.FMZは,公式に取引所のGPRのexeバージョンを時々公開する.GPRは,Pythonを使用して完成させることもできる.このとき,それは,通常のディスクとして,托管者の上で実行できる.

具体的合意について:https://www.fmz.com/bbs-topic/1052 Pythonで一般的なプロトコルを書く例:https://www.fmz.com/strategy/101399

独自の量子プラットフォームを 構築する

取引所のあらゆる操作がAPIで実現できるように,FMZウェブサイトもAPIベースのものです. FMZウェブサイトのAPI-KEYを実現するために,リクリエーション,再起動,リクリクリストの取得,リクリクログの取得などの様々な機能を申請できます.

FMZプラットフォームの強力な拡張性により,拡張APIに基づいて独自の定量化プラットフォームを作成し,ユーザーにあなたのプラットフォームで実機を稼働させることができます.

FMZのパートナーとして

オンライン・クラウド教室の普及

デジタル通貨取引市場は,その特異性により,定量化トレーダーの関心がますます高まっている.実際には,プログラム化された取引は,すでにデジタル通貨の主流であり,ヘッジメーティング市場などの戦略は,常に市場が活発である.プログラミングの基礎が弱い初心者は,この分野に入ろうとして,多数の取引所と多変なAPIに直面し,困難が重重である.発明者 (FMZ) の定量化プラットフォーム (原:BotVs,www.fmz.com) は,現在最大のデジタル通貨コミュニティの定量化プラットフォームであり,4年以上にわたって,数千人の初心者が定量化取引への道を進んできました.このコースは,わずか20ドルで,初心者向けである.

広めるデジタル通貨の量化取引の講座◎ オンライン教室にログインして,あなたのコースのリンクを共有してください (リンクは独自のコースIDを持っています),他の人がこのリンクを介して登録し,コースを購入すると,あなたは50%の合計10元の割引を受け取ります.

コミッション返還活動

消費者はプロモーションリンクをクリックし,半年以内に登録充值し,当社は有効な注文の有効な金額に応じて,コミッションを返金する. コミッションは,積分としてプロモーターの口座に返金され,ユーザーは10:1の比率で発明者を量化取引プラットフォームの口座余額に交換することができ,また,後に積分で発明者を量化することができます. 具体的活動リンク:https://www.fmz.com/bbs-topic/3828

FMZ 量化プラットフォームの企業版

FMZのウェブサイトは,約10万人のユーザーによって使用され,テストされ,高い可用性および安全性を達成し,量化チームと企業の時間コストを節約できます. 企業版は,中型量化取引チーム,商品期貨サービス業者などに向けられ,具体的なオファーを管理者に連絡してください.

市場システム

取引所向けに市場流動性と資金管理を提供する専門的なシステムで,多くの取引所やチームによって使用されている,おそらく市場で最も完ぺきな取引システムである.

エクスチェンジ・プログラム

発明者科技取引システムは,メモリカプセル技術を採用し,注文処理速度は最大200万ペンス/秒で,注文処理に遅延やカートンが発生しないことを保証できます.同時にオンラインユーザー数が200万人を超える取引所の流暢な安定した動作を維持できます.多層,多集群のシステムアーキテクチャは,システムの安全性,安定性,拡張性を保証します.機能展開,バージョン更新は,停止せずに実行され,端末のユーザー操作体験を最大限に保証します.現在,wex.app模擬取引所でこのシステムに体験することができます.