리소스 로딩... 로딩...

FMZ 중간 자습서

저자:초목, 2019-04-12 14:28:19, 업데이트: 2024-02-05 20:07:56

[TOC]

img

이 튜토리얼은 FMZ 플랫폼에 대한 더 많은 세부 사항을 다루고, API를 사용하는 방법에 대한 더 많은 실용적인 기술을 포함합니다. 이 중간 튜토리얼을 배우기 전에 초보자 튜토리얼을 읽고 FMZ에 대한 기본적인 이해가 있어야합니다.

전체 튜토리얼을 배운 후, FMZ를 최대한 활용하고 보다 맞춤형, 보다 효율적이고 더 복잡한 전략을 쓸 수 있을 것입니다.

1.다양한 교환을 추가하고 여러 개의 기호를 거래

하나의 로봇 안에서 여러 거래소와 여러 기호를 쉽게 거래할 수 있습니다.

  • 로봇을 시작할 때 하나 또는 여러 개의 교환을 추가합니다.
  • API는exchange.GetTicker()하나의 교환이 추가되면
  • 여러 개의 교환이 추가되면 API는exchanges[0].GetTicker(), exchanges[1].GetTicker() img
  • 같은 교환을 다른 기호로 추가할 수 있습니다.img
  • 당신은 결합하는 기호를 변경할 수 있습니다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)
  }
}

2.Trade미래에셋대우 및 스와프 계약

현재까지 FMZ는 OKEX, HuobiDM, BitMEX, GateIO 및 Deribit와 같은 모든 주요 선물 거래소를 지원하고 있습니다.

FMZ에서 선물 거래를 하기 위해서는 먼저 선물 거래소를 추가하고 로봇을 시작할 때 기호를 설정하고 코드에서 계약 유형을 설정해야 합니다.

만약 거래소가 스팟과 선물을 모두 지원한다면, FMZ에 따로 추가되어야 합니다.img

아래 그림은 봇을 시작할 때 미래에셋 기호를 BTC로 설정하는 방법을 보여줍니다.img

아래는 모든 거래소에 대한 계약 유형을 설정하는 방법입니다.

  • 오케이
    exchange.SetContractType("swap")        
    exchange.SetContractType("this_week")   
    exchange.SetContractType("next_week")  
    exchange.SetContractType("quarter")   
  • HuobiDM
    exchange.SetContractType("this_week")   
    exchange.SetContractType("next_week")  
    exchange.SetContractType("quarter")     
  • BitMEX
    exchange.SetContractType("XBTUSD")  
    exchange.SetContractType("XBTM19") 
  • 게이트IO
    exchange.SetContractType("swap")    
  • 데리비트
    exchange.SetContractType("BTC-PERPETUAL")  
    exchange.SetContractType("BTC-27APR18")

3.백테스트에 관한 것

기본 소개

FMZ는 두 가지 백테스팅 모드를 가지고 있습니다.real tick그리고simulate tick. 실제 틱 레벨은 전체 완료 된 역사 데이터를 포함합니다 (초당 한 틱), 그래서 백테스팅 결과는 더 신뢰할 수 있습니다. 시뮬레이션 레벨은 전략이 사용하는 간격에서 역사 클린 데이터를 사용합니다. 한 클린 내의 틱은 MT4와 동일한 알고리즘에 의해 생성됩니다. 더 자세한 내용은 여기에서 찾을 수 있습니다.https://www.mql5.com/en/articles/75한편, 더 짧은 간격은 틱을 생성하기 위해 기초-클라인으로 선택 될 수 있습니다. 시뮬레이션 틱 모드는 실제 틱 모드보다 훨씬 빠르지만 정확도가 낮다. 시뮬레이션 틱 모드의 짧은 클라인 간격은 정확성과 테스트 속도 사이의 타협이다.

백테스트 구성

기본 설정은 다음과 같습니다.img숨겨진 톱니:img

백테스트 결과

img

4.실점 허용성

교환 API에 액세스 하는 함수 (예를 들어GetTicker, Buy, CancelOrder, etc...), 당신은 교환 서버 문제, 잘못된 매개 변수, 네트워크 전송 문제 등으로 인해 액세스 실패를 얻을 수 있습니다. 이 경우 기능은 반환null그래서 오류를 처리하는 방법을 알아야 합니다.

뭐가 잘못됐어?

보트는 오류가 발생하면 오류 메시지를 반환합니다. 단지 교환 이름 + 오류 msg를 검색하면 문제가 무엇인지 찾을 수 있습니다. 예를 들어, 오류{"result":false,"error_code":20049}호출 때 반환됩니다.exchange.GetAccount()OKEX에서 구글에서OKEX 20049, 여기 결과가 있습니다:img또한 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
 } 

5.거래소와 직접 연결

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

모든 세부사항을 찾아보세요HttpQueryhttps://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를 위해,HttpQueryAPI 키, 기호, 해시 등을 처리해야 하기 때문에 매우 복잡할 것입니다.IO이 조건에 대한 편리한 함수입니다, 그것을 확인https://fmz-docs.readthedocs.io/en/latest/code_Instruction/Extent API.html#io. IO이 부분에서는 개인 API에 대한 접근에만 집중합니다.

이 함수를 사용하려면 먼저 거래소의 원래 API를 이해해야 합니다. 아래는 BitMEX에서 FMZ가 지원하지 않는 중지 주문을 만드는 단계입니다.

마지막 자바스크립트 코드:

var id = exchange.IO("api", "POST", "/api/v1/order", "symbol=XBTUSD&side=Buy&orderQty=1&stopPx=4000&ordType=Stop")

6.웹소켓 사용

기본적으로 모든 디지털 통화 거래소는 웹소켓을 통해 시장 데이터를 전송하는 것을 지원하며 일부 거래소는 계정 정보를 업데이트하는 것을 지원합니다. 나머지 API와 비교하면 웹소켓은 일반적으로 낮은 지연, 높은 주파수, 플랫폼 휴식 API 요청 주파수로 제한되지 않는 장점이 있습니다. 단점은 중단 될 수 있으며 처리가 직관적이지 않다는 것입니다.

자바스크립트를 사용하시면Dial웹소켓에 연결하는 함수입니다. 파이썬에서는Dial또는websocket_client libray.

이 튜토리얼은 자바스크립트를 사용하여 웹소켓을 연결하는 것에 초점을 맞출 것입니다.DialFMZ 퀀티제이션 플랫폼에서 기능. 다양한 사용을 확장하기 위해, 다이얼 기능은 여러 번 업데이트되었습니다. 이 튜토리얼은 웹소켓 기반 이벤트 구동 전략을 보여주고 여러 교환에 연결하는 방법을 보여줍니다.

웹소켓에 연결

  • 1.대부분의 경우, 당신은 직접 연결할 수 있습니다. 아래는 Binance 모든 티커에 연결하는 예입니다.
    var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
    
  • 2.압축된 형식의 반환 데이터의 경우 연결 시에 지정해야합니다.compress데이터가 압축된 형식이고 매개 변수mode전송 또는 수신이 압축되는지를 나타냅니다. OKEX에 연결하는 예
    var client = Dial("wss://real.okex.com:10441/websocket?compress=true|compress=gzip_raw&mode=recv")
    
  • 3. 다이얼 함수는 기본 언어인 Go 언어에 의해 자동 재결합을 지원합니다. 요청 데이터 컨텐츠는 이미 url에 있습니다. 예를 들어 Biannce의 예시와 같이 편리하고 권장됩니다. 구독 메시지를 보내야하는 사람들에게는 스스로 재결합을 유지할 수 있습니다.
    var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr?reconnect=true")
    
  • 4.Binance와 같은 일부 거래소 구독 채널이 url에 포함되어 있지만, 일부에서는 사용자가 구독 채널을 보내도록 요구합니다.
    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()
}
    

7.무동기 또는 멀티 스레딩

이제 우리가 가지고 있는 모든 코드는 단일 스레드, 순차적인 실행을 알아차렸을 수 있습니다. 원시 자바스크립트는 비동기 기능을 지원하지 않습니다. 그러나, FMZ는 기능을 제공합니다GO매우 제한적입니다.GoAPI 요청의 지연과 시간 소모에 대해 정말 신경쓰는 경우입니다.

교환.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까지 축적되고 오류를 반환합니다.

8.표 및 차트

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원본에 존재하지 않는 속성입니다.__isStockfalse가 되면, 차트는 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 img

9.전략 모델

템플릿은 많은 고급 기능을 포괄하는 라이브러리입니다. 이는 전략을 작성하는 것을 더 쉽게 만듭니다. 템플릿을 사용하기 위해서는 먼저 필요한 템플릿을 복사해야합니다. 예를 들어 자바스크립트 플롯 라이브러리를 가져가서https://www.fmz.com/strategy/27293그리고 저장. 그리고 전략 편집 페이지에서 선택하세요.img함수들은$.자바스크립트 템플릿에서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고마워요

초목이 튜토리얼을 준비 중이에요. 몇 일 정도 걸릴 겁니다. 궁금한 게 있으면 물어보세요.