[TOC]
이 튜토리얼은 FMZ 플랫폼에 대한 더 많은 세부 사항을 다루고, API를 사용하는 방법에 대한 더 많은 실용적인 기술을 포함합니다. 이 중간 튜토리얼을 배우기 전에 초보자 튜토리얼을 읽고 FMZ에 대한 기본적인 이해가 있어야합니다.
전체 튜토리얼을 배운 후, FMZ를 최대한 활용하고 보다 맞춤형, 보다 효율적이고 더 복잡한 전략을 쓸 수 있을 것입니다.
하나의 로봇 안에서 여러 거래소와 여러 기호를 쉽게 거래할 수 있습니다.
exchange.GetTicker()
하나의 교환이 추가되면exchanges[0].GetTicker()
, exchanges[1].GetTicker()
exchange
사용함으로써IO
기능var symbols = ["BTC_USDT", "LTC_USDT", "EOS_USDT", "ETH_USDT", "BCC_USDT"]
var buyValue = 1000
function main(){
for(var i=0;i<symbols.length;i++){
exchange.IO("currency", symbols[i]) // It is always valid until the next change
var ticker = exchange.GetTicker()
var amount = _N(buyValue/ticker.Sell, 3)
exchange.Buy(ticker.Sell, amount)
Sleep(1000)
}
}
현재까지 FMZ는 OKEX, HuobiDM, BitMEX, GateIO 및 Deribit와 같은 모든 주요 선물 거래소를 지원하고 있습니다.
FMZ에서 선물 거래를 하기 위해서는 먼저 선물 거래소를 추가하고 로봇을 시작할 때 기호를 설정하고 코드에서 계약 유형을 설정해야 합니다.
만약 거래소가 스팟과 선물을 모두 지원한다면, FMZ에 따로 추가되어야 합니다.
아래 그림은 봇을 시작할 때 미래에셋 기호를 BTC로 설정하는 방법을 보여줍니다.
아래는 모든 거래소에 대한 계약 유형을 설정하는 방법입니다.
exchange.SetContractType("swap")
exchange.SetContractType("this_week")
exchange.SetContractType("next_week")
exchange.SetContractType("quarter")
exchange.SetContractType("this_week")
exchange.SetContractType("next_week")
exchange.SetContractType("quarter")
exchange.SetContractType("XBTUSD")
exchange.SetContractType("XBTM19")
exchange.SetContractType("swap")
exchange.SetContractType("BTC-PERPETUAL")
exchange.SetContractType("BTC-27APR18")
기본 소개
FMZ는 두 가지 백테스팅 모드를 가지고 있습니다.real tick
그리고simulate tick
. 실제 틱 레벨은 전체 완료 된 역사 데이터를 포함합니다 (초당 한 틱), 그래서 백테스팅 결과는 더 신뢰할 수 있습니다. 시뮬레이션 레벨은 전략이 사용하는 간격에서 역사 클린 데이터를 사용합니다. 한 클린 내의 틱은 MT4와 동일한 알고리즘에 의해 생성됩니다. 더 자세한 내용은 여기에서 찾을 수 있습니다.https://www.mql5.com/en/articles/75한편, 더 짧은 간격은 틱을 생성하기 위해 기초-클라인으로 선택 될 수 있습니다.
시뮬레이션 틱 모드는 실제 틱 모드보다 훨씬 빠르지만 정확도가 낮다. 시뮬레이션 틱 모드의 짧은 클라인 간격은 정확성과 테스트 속도 사이의 타협이다.
백테스트 구성
기본 설정은 다음과 같습니다.숨겨진 톱니:
백테스트 결과
교환 API에 액세스 하는 함수 (예를 들어GetTicker
, Buy
, CancelOrder
, etc...), 당신은 교환 서버 문제, 잘못된 매개 변수, 네트워크 전송 문제 등으로 인해 액세스 실패를 얻을 수 있습니다. 이 경우 기능은 반환null
그래서 오류를 처리하는 방법을 알아야 합니다.
뭐가 잘못됐어?
보트는 오류가 발생하면 오류 메시지를 반환합니다. 단지 교환 이름 + 오류 msg를 검색하면 문제가 무엇인지 찾을 수 있습니다. 예를 들어, 오류{"result":false,"error_code":20049}
호출 때 반환됩니다.exchange.GetAccount()
OKEX에서 구글에서OKEX 20049
, 여기 결과가 있습니다:또한 Exchange API doc에서 오류 코드를 확인할 수 있습니다.OKEX Futures 에러 코드
거래 오류
전략 코드를 작성할 때 오류를 처리하는 방법을 고려해야 합니다. 다음은 몇 가지 예입니다:
// 1.Deal when the result is null
var ticker = exchange.GetTicker()
while(ticker == null){
Log('GetTicker error')
Sleep(100)
ticker = exchange.GetTicker()
}
Log(ticker.Last);
// 2.Refer when the result is not null
var ticker = exchange.GetTicker()
if(!ticker){
Log(ticker.Last)
}
// 3._C() fucntion retry
var ticker = _C(exchange.GetTicker) // can't apply _C to CancelOrder, Why?
Log(ticker.Last)
// 4. try catch
try{
var ticker = exchange.GetTicker()
Log(ticker.Last)
}
catch(err){
Log('GetTicker error: ', err)
Log(GetLastError()) //literal means, get last error
}
FMZ는 모든 다른 교환 데이터를 동일한 형식으로 포장하여 크로스 플랫폼 전략을 작성하는 것을 더 쉽게합니다. 그러나 추가 정보를 제공하는 특정 API의 특정 데이터를 얻을 수 없으며 FMZ가 지원하지 않는 API에 액세스 할 수 없습니다. 이 문제에 대한 두 가지 해결책이 있습니다.
GetRawJSON
마지막 REST API 요청에 의해 반환 된 원래 콘텐츠 (string) 를 반환합니다. 이는 직접 원료 정보를 분석하는 데 사용할 수 있습니다.
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
모든 세부사항을 찾아보세요HttpQuery
에https://fmz-docs.readthedocs.io/en/latest/code_Instruction/Global Function.html#
HttpQuery
이 요청의 원료 데이터를 반환합니다. 먼저 분석해야 합니다.
//FMZ doesn't have a standard function for exchangeInfo that return the trading-information about all symbols.
var exchangeInfo = JSON.parse(HttpQuery('https://api.binance.com/api/v1/exchangeInfo'))
Log(exchangeInfo) // FMZ doesn't have a standard function for this API
var ticker = JSON.parse(HttpQuery('https://api.binance.com/api/v1/ticker/24hr'))
Log(ticker)
공개된 API를 위해,HttpQuery
이 함수는 정말 유용합니다.HttpQuery
자바스크립트를 지원합니다. 파이썬에서는urlib2
또는request
라이브러리에서 HTTP 요청을 직접 전송합니다.
IO
그 개인 API를 위해,HttpQuery
API 키, 기호, 해시 등을 처리해야 하기 때문에 매우 복잡할 것입니다.IO
이 조건에 대한 편리한 함수입니다, 그것을 확인https://fmz-docs.readthedocs.io/en/latest/code_Instruction/Extent API.html#io. IO
이 부분에서는 개인 API에 대한 접근에만 집중합니다.
이 함수를 사용하려면 먼저 거래소의 원래 API를 이해해야 합니다. 아래는 BitMEX에서 FMZ가 지원하지 않는 중지 주문을 만드는 단계입니다.
POST
, 매개 변수에는 기호,사이드,orderQty,stopPx,ordType 등이 포함됩니다.마지막 자바스크립트 코드:
var id = exchange.IO("api", "POST", "/api/v1/order", "symbol=XBTUSD&side=Buy&orderQty=1&stopPx=4000&ordType=Stop")
기본적으로 모든 디지털 통화 거래소는 웹소켓을 통해 시장 데이터를 전송하는 것을 지원하며 일부 거래소는 계정 정보를 업데이트하는 것을 지원합니다. 나머지 API와 비교하면 웹소켓은 일반적으로 낮은 지연, 높은 주파수, 플랫폼 휴식 API 요청 주파수로 제한되지 않는 장점이 있습니다. 단점은 중단 될 수 있으며 처리가 직관적이지 않다는 것입니다.
자바스크립트를 사용하시면Dial
웹소켓에 연결하는 함수입니다. 파이썬에서는Dial
또는websocket_client
libray.
이 튜토리얼은 자바스크립트를 사용하여 웹소켓을 연결하는 것에 초점을 맞출 것입니다.Dial
FMZ 퀀티제이션 플랫폼에서 기능. 다양한 사용을 확장하기 위해, 다이얼 기능은 여러 번 업데이트되었습니다. 이 튜토리얼은 웹소켓 기반 이벤트 구동 전략을 보여주고 여러 교환에 연결하는 방법을 보여줍니다.
웹소켓에 연결
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")
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr?reconnect=true")
var client = Dial("wss://ws-feed.pro.coinbase.com", 60)
client.write('{"type": "subscribe","product_ids": ["BTC-USD"],"channels": ["ticker","heartbeat"]}')
데이터 수신
일반적으로 웹소켓의 데이터는 무궁무진한 루프에서 수면없이 지속적으로 읽을 수 있습니다. 코드는 다음과 같습니다:
function main() {
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
while (true) {
var msg = client.read() //receve data from client
var data = JSON.parse(msg) //change raw string to js object
// do something, don't need sleep.
}
}
웹소켓은 데이터를 매우 빠르게 푸시합니다. 도커의 기본은 대기열에 있는 모든 데이터를 캐시하고, 프로그램을 호출할 때 첫 번째 데이터를 반환합니다.read
로봇의 네트워크 동작은Buy
,GetAccount
,CancelOrder
트랜잭션 푸시, 계정 푸시, 서브셋 딥 푸시 등과 같은 정보에 대해서는 역사적인 데이터가 필요합니다. 시장 데이터에 대해서는 일반적으로 최신 데이터에만 관심이 있습니다.
이read()
이 함수는 변수가 없는 경우 대기열에서 가장 오래된 데이터를 반환하고, 데이터가 없는 경우 차단합니다 (프로그램이 여기서 일시 중지됩니다). 최신 데이터를 원한다면,read(-2)
즉시 최신 데이터를 반환하고null
만약 대기열에 데이터가 없다면 (프로그램은 일시 중지되지 않습니다).
여러 웹소켓에 연결
이 경우, 그것은 프로그램이 간단한 사용할 수 없다는 것이 분명합니다.read()
왜냐하면 교환은 새로운 데이터를 차단하고 기다리기 때문에 다른 교환은 즉시 자신의 새로운 데이터를 수신하지 않을 것입니다. 일반적인 치료는:
function main() {
var binance = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
var coinbase = Dial("wss://ws-feed.pro.coinbase.com")
coinbase.write('{"type": "subscribe","product_ids": ["BTC-USD"],"channels": ["ticker","heartbeat"]}')
while (true) {
var msgBinance = binance.read(-1)
var msgCoinbase = coinbase.read(-1)
if(msgBinance){
// Binance has new data
}
if(msgCoinbase){
// coinbase has new data
}
Sleep(1) // just sleep 1ms
}
}
웹소켓을 사용하는 일반적인 프레임워크
푸시 데이터가 이미 사용되었기 때문에, 프로그램은 자연스럽게 API 요청 빈도에 주의를 기울여 이벤트 주도형으로 작성됩니다.
var tradeTime = Date.now()
var accountTime = Date.now()
function trade(data){
if(Date.now() - tradeTime > 2000){//only trade once within 2s
tradeTime = Date.now()
//trading code
}
}
function GetAccount(){
if(Date.now() - accountTime > 5000){//only get account once within 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(Address, Timeout)
:
Timeout
: 연결 종료 시간
주소는 다른 매개 변수들에 의해 따라질 수 있습니다.&
주소와 매개 변수는|
,
매개 변수 | 설명 |
---|---|
압축 | 압축 방법,gzip_raw , gzip . OKEX 사용gzip_raw |
모드 | 될 수 있습니다.dual 전송과 수신이 압축되어야 한다는 것을 의미합니다.send 압축 될 필요를 전송하고recv 받는다는 뜻입니다. |
대리자 | ss5의 프록시 설정socks5://name:pwd@192.168.0.1:1080 |
다시 연결 | Reconnect=true 다시 연결할 수 있도록 |
간격 | interval 재시험 간격입니다. 기본값은 1000ms입니다. |
유해물 | wss가 다시 연결될 때 보내야 하는 구독 메시지 |
그 매개 변수read()
:
웹소켓이 끊어졌을 때,read()
빈 문자열을 반환합니다.
매개 변수 | 아무 것도 없습니다 | -1 | -2 | 2000 |
---|---|---|---|---|
대기열이 비어있지 않네요 | 가장 오래된 데이터를 즉시 반환 | 가장 오래된 데이터를 즉시 반환 | 가장 최근의 데이터를 즉시 반환 | 가장 오래된 데이터를 즉시 반환 |
대기열이 비어있어요 | 새로운 데이터가 돌아오기 전까지 차단 | 반환null 즉시 |
반환null 즉시 |
새로운 데이터가 돌아오기 전까지 2000ms 미만 기다립니다. 그렇지 않으면 반환합니다.null |
의 사용close()
:
웹소켓 연결을 닫습니다.
function main() {
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr|reconnect=true")
client.close()
}
이제 우리가 가지고 있는 모든 코드는 단일 스레드, 순차적인 실행을 알아차렸을 수 있습니다. 원시 자바스크립트는 비동기 기능을 지원하지 않습니다. 그러나, FMZ는 기능을 제공합니다GO
매우 제한적입니다.Go
API 요청의 지연과 시간 소모에 대해 정말 신경쓰는 경우입니다.
교환.Go (방법, Args)
방법: 함수 이름. Args: 방법의 주장.
지원 함수 목록:GetTicker
, GetDepth
, GetTrades
, GetRecords
, GetAccount
, GetOrders
, GetOrder
, CancelOrder
, Buy
, Sell
, GetPosition
.
자바스크립트 예제:
function main(){
var a = exchange.Go("GetTicker"); //GetTicker Asynchronous multithreaded execution
var b = exchange.Go("GetDepth");
var c = exchange.Go("Buy", 1000, 0.1);
var d = exchange.Go("GetRecords", PERIOD_H1);
// The above four operations are concurrent multi-threaded asynchronous execution, will not block and immediately return
var ticker = a.wait(); // Call wait method wait for return to asynchronous get ticker result
var depth = b.wait(); // Return depth, it is also possible to return null if it fails
var orderId = c.wait(1000); // Return the order number, 1 second timeout, timeout returns undefined, this object can continue to call wait until the last wait timeout
var records = d.wait(); // Wait for K-line result
var ret = d.wait(); // Here waits for an asynchronous operation that has waited and ended, returns null, and logs an error message.
}
wait()
함수는 다음으로 호출되어야 합니다.Go
이 함수, 그렇지 않으면, 스레드 리소스는 2000까지 축적되고 오류를 반환합니다.
LogStatus
그리고 테이블
로그국가는 보트 상태 표시줄에서 메시지 또는 테이블을 로그화하고, 매번 갱신합니다.
//Normal uses of LogStatus
LogStatus(" This is a normal status prompt")
LogStatus(" This is a red font status prompt #ff0000")
LogStatus(" This is a multi-line status message\n I'm the second line")
로그국가는 로봇 페이지에 테이블을 로그 할 수 있습니다. 추가`
양쪽 모두에 문자를 표시하고 복잡한 메시지 형식으로 처리합니다 (현재 지원되는 테이블)
var table = {type: 'table', title: ' Account information support color #ff0000', cols: ['BTC', 'ETH', 'USDT'], rows: [ ['free', 1, 2000], ['frozen', 0, 3000]]}
LogStatus('`' + JSON.stringify(table)+'`')
//Another example, information can also appear in multiple lines:
LogStatus("First line message\n" + JSON.stringify(table)+"`\n third line message")
//Log multiple tables in a group, switching by TAB:
var table1 = {type: 'table', title: ' Account information 1', cols: ['BTC', 'ETH', 'USDT'], rows: [ ['free', 1, 2000], ['frozen', 0, 3000]]}
var table2 = {type: 'table', title: ' Account information 2', cols: ['BTC', 'ETH', 'USDT'], rows: [ ['free', 1, 2000], ['frozen', 0, 3000]]}
LogStatus('`' + JSON.stringify([table1, table2])+'`')
차트
로봇 관리 페이지에 숫자를 그리세요.
차트 지원 하이스톡 및 하이스차트, 체크https://www.highcharts.com/demo그리고https://www.highcharts.com/stock/demo더 많은 예제를 위해.
차트 객체는__isStock
원본에 존재하지 않는 속성입니다.__isStock
false가 되면, 차트는 HighCharts로 표시됩니다.__isStock
사실입니다, 차트는 HighStocks로 표시됩니다.reset()
그래프 데이터를 정리하기 위해서요.
두 개의 기호의 가격을 그리기 위해 차트를 사용하는 자바스크립트 예제:
// This chart is an object in the JS language. Before using the Chart function, we need to declare an object variable chart that configures the chart.
var chart = {
// Whether the mark is a general chart, if you are interested, you can change it to false and run it.
__isStock: true,
tooltip: {xDateFormat: '%Y-%m-%d %H:%M:%S, %A'}, // Zoom tool
title : { text : 'Spread Analysis Chart'}, // title
rangeSelector: { // Selection 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'}, // The horizontal axis of the coordinate axis is the x axis and the current setting type is :time
yAxis : { // The vertical axis of the axis is the y axis, and the default value is adjusted with the data size.
title: {text: 'Spread'}, // title
opposite: false, // Whether to enable the right vertical axis
},
series : [ // Data series, this attribute is saved for each data series (line, K-line graph, label, etc...)
{name : "line1", id : "Line 1,buy1Price", data : []}, // The index is 0, the data array is stored in the index series of data
{name : "line2", id : "Line 2,lastPrice", dashStyle : 'shortdash', data : []},
// The index is 1, dashStyle is set: 'shortdash' ie: Set the dotted line.
]
};
function main(){
var ObjChart = Chart(chart); // Call the Chart function to initialize the chart.
ObjChart.reset(); // Empty the chart
while(true){
var nowTime = new Date().getTime(); // Get the timestamp of this poll, which is a millisecond timestamp. Used to determine the position of the X axis written to the chart.
var tickerOne = _C(exchanges[0].GetTicker); // Get market data
var tickerTwo = _C(exchanges[1].GetTicker);
ObjChart.add([0, [nowTime, tickerOne.Last]]); // Use the timestamp as the X value and buy the price as the Y value to pass the index 0 data sequence.
ObjChart.add([1, [nowTime, tickerTwo.Last]]); // Same as above
ObjChart.update(chart); // Update the chart to show it.
Sleep(2000);
}
}
다중 그림 표시를 지원합니다. 전체 예제:https://www.fmz.com/strategy/136056
템플릿은 많은 고급 기능을 포괄하는 라이브러리입니다. 이는 전략을 작성하는 것을 더 쉽게 만듭니다. 템플릿을 사용하기 위해서는 먼저 필요한 템플릿을 복사해야합니다. 예를 들어 자바스크립트 플롯 라이브러리를 가져가서https://www.fmz.com/strategy/27293그리고 저장. 그리고 전략 편집 페이지에서 선택하세요.함수들은$.
자바스크립트 템플릿에서ext.
파이썬 템플릿에서
function main() {
var isFirst = true
while (true) {
var records = exchange.GetRecords();
if (records && records.length > 0) {
$.PlotRecords(records, 'BTC')
if (isFirst) {
$.PlotFlag(records[records.length - 1].Time, 'Start', 'S')
isFirst = false
$.PlotHLine(records[records.length - 1].Close, 'Close')
}
}
var ticker = exchange.GetTicker()
if (ticker) {
$.PlotLine('Last', ticker.Last)
$.PlotTitle('Last ' + ticker.Last)
}
Sleep(60000)
}
}
여기 플롯 템플릿을 사용하는 또 다른 간단한 예가 있습니다:https://www.fmz.com/strategy/121917
q25459768고마워요
초목이 튜토리얼을 준비 중이에요. 몇 일 정도 걸릴 겁니다. 궁금한 게 있으면 물어보세요.