[TOC] このトークを学ぶ前に,まず学ぶ必要があります.FMZの発明者による量化プラットフォームの導入そしてFMZ量化プラットフォーム戦略 初級チュートリアル作成プログラミング言語を熟知している.初級チュートリアルでは最もよく使われる関数を扱いますが,多くの関数や機能が紹介されていないので,このチュートリアルではカバーされません.プラットフォームAPIのドキュメントを閲覧する必要があります.このチュートリアルで,より自由で,よりカスタマイズされた戦略を書くことができます. FMZプラットフォームは単なるツールです.
FMZプラットフォームは,サポートされているすべての取引所にパッケージ化されており,統一性を保つため,個々の取引所のAPIサポートは完全ではありません.例えば,K線を取得することは,通常K線の数や開始時間を通過させることができます.公開インターフェース (例:行業) では使用できます.HttpQuery
アカウント情報へのアクセスについては,IO
。特定の入力パラメータについては,関連する取引所のAPI文書を参照してください. 前回のチュートリアルで説明されています.Info
フィールドは元の情報を返却したが,インターフェースがサポートされていない問題をまだ解決できない.
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)
}
Jsで使える公開インターフェースにアクセスしますHttpQuery
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()
API-KEY署名を必要とするインターフェースでは,IO関数を使用することができ,ユーザーは入力パラメータだけを気にする必要があり,特定の署名プロセスは底層で完了します.
FMZプラットフォームは,現在BitMEXストップデートをサポートしていません.
https://www.bitmex.com/api/explorer/
。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")
//也可以直接传入对象
var id = exchange.IO("api", "POST", "/api/v1/order", "", JSON.stringify({symbol:"XBTUSD",side:"Buy",orderQty:1,stopPx:4000,ordType:"Stop"}))
海外のメディアは,https://www.fmz.com/bbs-topic/3683
基本的にはすべての仮想通貨取引所がwebsocket送信市場をサポートし,一部の取引所がwebsocketアカウント情報を更新することをサポートしている. rest APIと比較して,websocketは一般的に遅延が低く,頻度が高く,プラットフォームrest APIの頻度制限を受けていない.
この記事では主にFMZの発明者定量化プラットフォーム,JavaScript言語を使用し,プラットフォームに包まれたDial関数を使用して接続,文書に詳細な説明とパラメータ,Dial検索,さまざまな機能を実現するためにDial関数にいくつかの更新が実施されていることを説明し,wssベースのイベント駆動策略,および複数の取引所接続の問題について説明します. PythonでもDial関数を使用し,関連するライブラリを使用することができます.
簡単に簡単に接続できるのは,コインのセキュリティティッカーを押す方法です.
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の中にあり,ちょうどBinanの例のように,非常に便利で,使用することが推奨される. メッセージを送信する必要のある人は,自己維持の再接続メカニズムを使用することができます.
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr|reconnect=true")
WWSのメッセージへの購読,いくつかの取引所の要求はURLに,またCoinbaseのような自己購読を送信する必要があるチャンネルもあります:
client = Dial("wss://ws-feed.pro.coinbase.com", 60)
client.write('{"type": "subscribe","product_ids": ["BTC-USD"],"channels": ["ticker","heartbeat"]}')
Webソケットは,一般的には市場を読み取るために使用されますが,注文を取得したり,アカウントをプッシュしたりすることもできます. このような暗号化されたデータのプッシュは,時には非常に遅いので,慎重に使用する必要があります. 暗号化方法がより複雑であるため,いくつかの例が参照されています. 注意してください. すべては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)
}
}
死亡サイクルでは,通常,このコードは次のように読み続けられます.
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には異なるパラメータがあり,具体的には以下の図のように,複雑に見えるが,プログラムをより柔軟にする.
このケースでは,単純に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
}
}
この部分は,プッシュデータが中断される可能性があるため,またはプッシュの遅延が非常に高いため,この部分は処理が困難である.ハートビットを受信してもデータがまだプッシュされていることを意味しない場合でも,イベント間隔を設定し,間隔を超えると更新が受信されない場合は再接続し,データが正確かどうかを確認するために,時間間隔とrestを比較することが好ましい.この特殊なケースでは,自動的に再接続を直接設定できます.
プッシュデータは既に使用されているため,プログラムは自然にイベントドライバとして書き,データを頻繁にプッシュするように注意し,過剰なリクエストが封鎖につながらないようにしてください.
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)
}
}
各取引所のウェブソケットの接続方法,データ送信方法,サブスクリプション可能な内容,データ形式はしばしば異なるため,プラットフォームはパッケージ化されていないため,Dial関数で自動的に接続する必要があります.この記事は基本的にいくつかの基本的な注意事項をカバーしています.
PS.いくつかの取引所は,websocketの市場を提供していないが,実際に登入サイトを調節機能を使用している場合,Websocket推送を使用していることがわかります. 調べてみると,サブスクリプション形式とリターン形式が表示されます.
JavaScriptはGo関数で並行を実現し,Pythonは対応するマルチスレッドリバリーを使用する.
量化戦略を実装する際に,多くの場合,並行実行は遅延提昇効率を低下させる.ヘッジ戦略の実態盤の例として,二つのコインの深さを取得する必要がある.
var depthA = exchanges[0].GetDepth()
var depthB = exchanges[1].GetDepth()
Rest APIのリクエストに遅延がある場合, 100ms と仮定すると, 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)
}
}
簡単な機能のみを実現するような回転が実際にコードの複雑さを大幅に簡素化している. プログラムが何を生成する必要があるかだけを気にする必要があり,作業者 (worker) プログラムによって自動的に並行して実行され,対応した結果が返されます. 柔軟性が非常に向上しています.
初級チュートリアルの紹介図図は,図図図のライブラリを推奨し,ほとんどの場合,必要を満たす.さらにカスタマイズする必要がある場合は,直接図図オブジェクト操作することができます.
Chart({…})
内部参数は,HighStockとHighChartsのオブジェクトで,ただ1つの参数を追加するだけです.__isStock
ハイストックであるかどうかを区別するために. ハイストックがタイムシーケンスに重点を置くチャートであるため,より頻繁に使用される. FMZは基本的にはHighChartsとHighStockの基本モジュールをサポートしますが,追加のモジュールをサポートしません.
この記事へのトラックバック一覧です.https://www.highcharts.com/demoハイストックの例:https://www.highcharts.com/stock/demoこの例のコードは,FMZに簡単に移植できます.
add (([series index ((例えば0),データ]) を呼び出すと,指定されたインデックスにseries を追加し,reset (reset) を呼び出す.空のグラフデータ,reset は数値参数を持って,予約された項目を指定することができます.複数のグラフを表示するサポート,設定時に数値参数を送信するだけで,例えば: var chart = Chart (([{...}, {...}, {...})),例えば,グラフ一には2つのseriesがあり,グラフは1つのseries,グラフは3つのseriesを持っています.
具体例として:
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);
}
}
グラフのレイアウトを使用した例:https://www.fmz.com/strategy/136056
オープンソースのアドレスは: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線データでは,1K線が1分である場合,リセットの底辺K線周期も1分に設定される.
サポートされていない取引所とサポートされている取引所のAPIが完全に同じで,ベースアドレスが異なる場合,ベースアドレスを切り替える方法によってサポートできます.特に,取引所を追加する際にサポートされている取引所を選択しますが,API-KEYがサポートされていない取引所を満たす場合は,戦略ではIOでベースアドレスを切り替える.例えば:
exchange.IO("base", "http://api.huobi.pro")
//http://api.huobi.pro为为支持交易所API基地址,注意不用添加/api/v3之类的,会自动补全
FMZはすべての取引所ではサポートされていませんが,このプラットフォームは,一般的なプロトコルへのアクセスを提供しています.
簡単に言えば,通用プロトコルは,管理者の要求を代理し,その基準に従ってデータを返した仲介者のようなものである.通用プロトコルのコードは自分で完了する必要があります.通用プロトコルの書き込みは,実際にはあなたが単独で取引所にアクセスしてポリシーを実行することを代表します.FMZの公式は,時には取引所の通用プロトコルのexeバージョンをリリースします.通用プロトコルは,Pythonを使用して完了することもできます.この場合は,通常の実体ディスクとして管理者上で実行できます.
具体的協定の説明:https://www.fmz.com/bbs-topic/1052Pythonのプロトコルの例:https://www.fmz.com/strategy/101399
FMZのウェブサイトもAPIベースのもので,自分のFMZのウェブサイトAPI-KEYの実装を申請できる.例えば,リアルディスクを作成,再起動,削除,リアルディスクリストを取得,リアルディスクログを取得など様々な機能を適用できます.
FMZプラットフォームの強力な拡張性により,拡張APIに基づいて自分の量化プラットフォームを作成し,ユーザがあなたのプラットフォームで実体盤を走らせることができます.詳細はhttps://www.fmz.com/bbs-topic/1697 に参照してください.
デジタル通貨取引市場は,その特異性により,量化トレーダーの関心がますます高まっているため,実際にプログラム化取引は既にデジタル通貨の主流であり,ヘッジ市場などの戦略は常に市場に活跃している. プログラミング基礎が弱い初心者がこの分野に入ろうとする場合は,多数の取引所と多変なAPIに直面し,困難を重くします. FMZの発明者 (元BotVs),www.fmz.comデジタル通貨の定量化コミュニティとプラットフォームとして,4年以上にわたり,何千人もの初心者が定量化取引への道を歩むのを助けています. このコースはわずか20ドルで初心者向けです.
広めるデジタル通貨量化取引のコース・ネット易雲教室にログインし,あなたのコースリンクをシェアします. ・リンクは独自のコースIDを持っています. ・他のユーザーがこのリンクを使用して登録し,コースを購入すると,あなたは50%の合計10元の分け方を得ます. ・ネット易雲教室精品コースのプロモーションに注目してください. ・微信公众号を即座に引き出すことができます. ・微博QQグループでプロモーションを招待してください.
消費者はプロモーションリンクをクリックし,半年以内に登録して充電すると,当社は有効な注文の有効金額に応じて佣金返済します. 佣金はポイントの形でプロモーターのアカウントに戻されます. ユーザーは,10:1の割合で発明者の量化取引プラットフォームの口座残高を交換することができます. また,後に分を交換して発明者の量化周辺商品を交換することができます. 特定の活動リンク:https://www.fmz.com/bbs-topic/3828
FMZウェブサイトは,約10万人のユーザーによる使用とテストを経て,高度な可用性と安全性,量化チームおよび企業の時間コスト削減を達成した.企業版は,量化取引チーム,商品フューチャーサービス提供者など,特定のオート管理者向けである.
市場流動性や資金管理を提供する専門システムは,おそらく市場で最も完全な市場管理システムであり,多くの取引所やチームによって使用されています.
発明者の科技取引システムは,メモリ撮影技術を採用し,注文処理速度が200万ペンス/秒までで,注文処理に遅延やキャッティングが発生しないことを保証することができる.同時にオンラインユーザー数が2000万人以上の取引所を流暢に安定して動作させることができる.多層,多集群のシステムアーキテクチャは,システムの安全性,安定性,拡張性,機能部署,バージョン更新を最大限に停止する必要なく行うことを保証する.現在,wex.appアニメ取引所でこのシステムを体験することができます.
2009年に結婚したグループに入れるか?
マイケオ草神,武神!
小草` ` //トークンフューチャープッシュの例 var ACCESSKEYID = 'あなたのトークンアカウントのアクセスキー' var apiClient = Dial (('wss://api.hbdm.com/notificationで圧縮する=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 タイムスタンプ = utc_date.toISOSstring (().substring ((0,19) var quest = 'GET\napi.hbdm.com\n/notification\n'+'AccessKeyId='+ACCESSKEYID+'&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=' + encodeURIComponent (タイムスタンプ) について var signature = exchange.HMAC (("sha256", "base64", quest, "{{secretkey}}")) は,SHA256の署名を表示している. ` `
ビート軍団Webソケットが接続しているサブスクリプション市場であれば, read (()) 関数で市場データを取得します. トークン一社のみが,exchange.IO ("websocket") によって市場受容方法を変更し,その後,exchange.GetTicker (株) と exchange.GetDepth (株) で取引所restからデータをリクエストせず,現地バッファーの既存の受注市場からgetデータを取得することをサポートしている. 私はそれを理解している,そうですか?
小草提示された確認に従ってください.
ジズリウユ確認は,今,FMZ電報グループで
シャルティエルわかった
小草ウェブソケットは Dial を使って,直感的に操作できます.