取引命令の通知 価格: 1000, // 注文の価格;この市場注文の属性は0または-1かもしれないことに注意 金額: 10, // 注文の金額を配置する; この市場オーダーの属性はコイン番号ではなく,金銭の金額であるかもしれないことに注意 DealAmount : 10, // 実行されたボリューム; プラットフォームインターフェイスがこのようなデータを提供していない場合は,おそらく 0 を入力します AvgPrice: 1000, // 実行された平均価格;いくつかのプラットフォームがこのデータを提供していないことに注意してください. (データを提供または計算できない状況では,属性の設定は0です.) 状態: 1, // 順序の状態; ORDER_STATE_CLOSED のような常数で順序の状態を参照 型: 0, // Order type; ORDER_TYPE_BUY のような定数で Order type を参照する オフセット: 0 // 暗号通貨先物取引のオーダーデータにおけるオーダーの開閉方向;ORDER_OFFSET_OPENは開いたポジションで,ORDER_OFFSET_CLOSEは閉じる方向です ContractType : // この属性は,即時注文,すなわちゼロ文字列のためのです.先物注文の属性は特定の契約コードです. { \ pos (192,220) }


##### MarketOrder

Market depth order, that is, ```exchange.GetDepth()``` returns the data structure of the elements in the **Bids** and **Asks** arrays in the data.

```javascript
{
    Price   : 1000,              // Price
    Amount  : 1                  // Volume
}
深さ

市場深さは関数で返されます.exchange.GetDepth().

{
    Asks    : [...],             // The array of sell orders, namely MarketOrder array, sorted by price from low to high
    Bids    : [...],             // The array of buy orders, namely MarketOrder array, sorted by price from high to low
    Time    : 1567736576000      // Millisecond-level timestamp
}
口座

関数で返されるアカウント情報exchange.GetAccount()構造で返されるデータは,現在設定されている取引ペアと契約コードに関連しています.

{
    Info            : {...},     // After requesting the platform interface, this attribute is not available in the raw data that the platform interface responds to, during the backtest
    Balance         : 1000,      // The available amount of quote currency; if the trading pair is BTC_USDT in the spot trading, "balance" refers to the current USDT amount. In the USDT-margined futures contract, "balance" refers to the available margin amount in USDT
    FrozenBalance   : 0,         // Here "balance" refers to the frozen amount of the assets for pending orders
    Stocks          : 1,         // The available amount of base currency; if the trading pair is BTC_USDT in the spot trading, "stocks" refers to the current BTC amount. In the crypto-margined futures contract, "stocks" refers to the available margin amount (base currency)
    FrozenStocks    : 0          // Here "stocks" refers to the frozen amount of the assets for pending orders
}
位置

フューチャー取引におけるポジションに関する情報については,配列このPosition構造は関数によって返されます.exchange.GetPosition() function.

{
    Info            : {...},     // After requesting the platform interface, this attribute is not available in the raw data that the platform interface responds to, during the backtest
    MarginLevel     : 10,        // The leverage size of positions; if this data is not provided by the platform interface, fill in the data by calculation, possibly with errors
    Amount          : 100,       // Position volume; the contract quantity of positions is normally positive integer. Notice every platform might have different contract specifications, such as contract multiplier and value, etc., so the rules for ordering might be different; for example, Binance contract might order by 0.1
    FrozenAmount    : 0,         // The quantity of frozen positions, used as the number of temporary position freeze when close positions and pending orders
    Price           : 10000,     // Average position price; in principle, the attribute is the average price of the entire position (which does not involve in the settlement); if the platform interface does not provide the data, use the existing average position price of the platform to fill in (which involves in the settlement)
    Profit          : 0,         // Position floating profit and loss, namely the failure of realizing position profit and loss. If the platform interface does not provide the data, use other profit and loss data from the interface to fill in; the unit of the profit and loss values is the same as the unit of the current contract margin 

    Type            : 0,         // PD_LONG is a long position, while PD_SHORT is a short position
    ContractType    : "quarter", // Contract code; for more details, refer to the transmitted parameters in the description of the function "SetContractType"
    Margin          : 1          // Margin occupied by positions; if the platform interface does not provide the data, use 0 to fill in
}

クリプトコインの先物については,Position函数によって返される構造配列exchange.GetPosition()位置データ構造の属性については,FrozenAmount, ProfitそしてMargin異なる交換オブジェクトによって返される可能性があります.exchange.GetPosition()例えば,いくつかの取引所は,位置凍結データを含まない.FrozenAmount属性でソースデータを使用できます. この属性では,Info計算と分析のために

グローバル 機能

バージョン

Version()返される値は:文字列タイプ.

睡眠 (ミリ秒)

Sleep(Millisecond)パラメータ値: プログラムが停止するMillisecond数字型である.パラメータ単位はミリ秒である.例えば:Sleep(1000)"秒寝る"という意味です 睡眠時間が1ミリ秒未満のサポート操作,例えば設定Sleep (0.1). サポートされている最小パラメータは0.000001睡眠のナノ秒です 1ナノ秒は1e-6 milliseconds.

注記: 戦略を書き出すときPython言語,機能Sleep(Millisecond)投票間隔や待機時間などの操作に使用する必要があります.time.time(second)についてtime図書館Pythonこの関数を使うとtime.time(second)戦略プログラムが実際に一定の数秒 (パラメータsecondストラテジーのバックテストが非常に遅くなる.

IsVirtual (バーチャル)

IsVirtual()復元値: bool タイプ シミュレーションされたバックテスト状態が返されますtrueそして本物のロボットが戻ってくるfalse.

郵便局から

Mail(smtpServer, smtpUsername, smtpPassword, mailTo, title, body)はメール送信関数です. パラメータ値: すべては文字列型です. 返却値: bool型です.true送信が成功した後で返却されますsmtpServer送信メールボックスのために使用されます.smtp; smtpUsernameメールボックスアカウントです.smtpPasswordメールボックス STMP パスワードです.mailTo受信メールボックスアカウントです.title送信された郵便のタイトルです.body送信されたメールの内容,例えば:

function main(){
    Mail("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
}
def main():
    Mail("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
void main() {
    Mail("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body");
}
  • についてMail_Go機能の非同期バージョンですMailについて この機能は,exchange.Go.

    function main() {
        var r1 = Mail_Go("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
        var r2 = Mail_Go("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
        
        var ret1 = r1.wait()
        var ret2 = r2.wait()
        
        Log("ret1:", ret1)
        Log("ret2:", ret2)
    }
    
    # Not supported
    
    // Not supported
    

注記: アリババ クラウド サーバーは,いくつかのポートをブロックし,メールが送信できない可能性があります. ポートを変更する必要がある場合は,最初のパラメータに直接ポート番号を追加することができます.smtp.qq.com:587(QQmail),ポートはテストのために利用可能です. エラーが発生した場合:unencrypted connectionパラメータの形式を変更する必要があります.smtpServer機能の中でMailについて:ssl://xxxxx.com:xxx例えば,QQmail の SMTP ssl メソッド:ssl://smtp.qq.com:465またはsmtp://xxxxx.com:xxx.

SetErrorFilter (エラーフィルタをセットする)

ErrorFilter(RegEx)パラメータ値:文字列タイプ この正規式で一致するエラーはログシステムにアップロードされず,複数の呼び出しが可能です (頻繁にエラー報告が引き起こされるデータベースファイル拡張を防ぐために,ドッカーコンテンツのログ/ボットで対応するボットIDのデータベースファイルにフィルタリングされたログは書き込まれません).

function main() {
    SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused")
}
def main():
    SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused")
void main() {
    SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused");
}

インターフェースのエラー情報をフィルタリングする:

function main() {
    // Randomly check a non-existent order with ID 123; intentionally make the interface report an error
    var order = exchange.GetOrder("123")
    Log(order)
    // Filter http502 errors and GetOrder interface errors; after set the error filter, the second time to call GetOrder no longer reports errors
    SetErrorFilter("502:|GetOrder")
    order = exchange.GetOrder("123")
    Log(order)
}
def main():
    order = exchange.GetOrder("123")
    Log(order)
    SetErrorFilter("502:|GetOrder")
    order = exchange.GetOrder("123")
    Log(order)
void main() {
    TId orderId;
    Order order = exchange.GetOrder(orderId);
    Log(order);
    SetErrorFilter("502:|GetOrder");
    order = exchange.GetOrder(orderId);
    Log(order);
}

GetPid (ゲットピッド)

GetPid()ボットプロセスの ID を返します. 返した値:文字列タイプ.

function main(){
    var id = GetPid()
    Log(id)
}
def main():
    id = GetPid()
    Log(id)
void main() {
    auto id = GetPid();
    Log(id);
}

削除する

GetLastError()最新のエラー情報を取得します.通常,このプログラムは自動的にログシステムにエラー情報をアップロードするため,使用する必要はありません.返却値:文字列タイプ.関数を呼び出す後GetLastError(),エラーキャッシュはクリアされます. また呼び出すと,最後に記録されたエラー情報は返されません.

function main(){
    // Because the order with ID number of 123 does not exist, an error is reported
    exchange.GetOrder("123")
    var error = GetLastError()
    Log(error)
}
def main():
    exchange.GetOrder("123")
    error = GetLastError()
    Log(error)
void main() {
    // The type of order ID: TId; so no string can be passed in, and we can trigger it by placing an order that does not meet the exchange specifications
    exchange.GetOrder(exchange.Buy(1, 1));
    auto error = GetLastError();
    Log(error);
}

コマンドを取得する

GetCommand()インタラクティブなコマンド (utf-8) を取得する. 戦略インタラクティブなインターフェースから送信されたコマンドを取得し,キャッシュをクリアする.コマンドがない場合は,空の文字列を返します. 返されるコマンド形式はbutton name: parameterインタラクティブなコントロールにパラメータがない場合 (例えば,入力ボックスのないボタンのコントロール),コマンドはボタンの名前です.

function main(){
    while(true) { 
        var cmd = GetCommand()
        if (cmd) { 
            Log(cmd)
        }
        Sleep(1000) 
    }
}
def main():
    while True:
        cmd = GetCommand()
        if cmd:
            Log(cmd)
        Sleep(1000)
void main() {
    while(true) {
        auto cmd = GetCommand();
        if(cmd != "") {
            Log(cmd);
        }
        Sleep(1000);
    }
}

インタラクティブなコマンドを記録するキュー構造があります.GetCommand()コマンドが呼び出されると,配列に最初に入力したインタラクティブコマンドが取り出されます (インタラクティブコマンドがない場合は,空の文字列です)

インタラクティブなコントロールを使用する例; 戦略編集インターフェイスでインタラクティブなコントロールを設定する:

img

戦略におけるインタラクティブなコードの設計:

function main() {
    while (true) {
        LogStatus(_D())
        var cmd = GetCommand()
        if (cmd) {
            Log("cmd:", cmd)    
            var arr = cmd.split(":")
            if (arr[0] == "buy") {
                Log("Buy, the control without quantity")
            } else if (arr[0] == "sell") {
                Log("Sell, the control with quantity: ", arr[1])
            } else {
                Log("Other controls trigger:", arr)
            }
        }
        Sleep(1000)
    } 
}
def main():
    while True:
        LogStatus(_D())
        cmd = GetCommand()
        if cmd:
            Log("cmd:", cmd)
            arr = cmd.split(":")
            if arr[0] == "buy":
                Log("Buy, the control without quantity")
            elif arr[0] == "sell":
                Log("Sell, the control with quantity:", arr[1])
            else:
                Log("Other controls trigger:", arr)
        Sleep(1000)
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
void split(const string& s,vector<string>& sv,const char flag = ' ') {
    sv.clear();
    istringstream iss(s);
    string temp;

    while (getline(iss, temp, flag)) {
        sv.push_back(temp);
    }
    return;
}

void main() {
    while(true) {
        LogStatus(_D());
        auto cmd = GetCommand();
        if (cmd != "") {
            vector<string> arr;
            split(cmd, arr, ':');
            if(arr[0] == "buy") {
                Log("Buy, the control without quantity");
            } else if (arr[0] == "sell") {
                Log("Sell, the control with quantity:", arr[1]);
            } else {
                Log("Other controls trigger:", arr);
            }
        }
        Sleep(1000);
    }
}

GetMeta (メタ) を取得する

機能についてGetMeta()値を返します.Meta戦略トークンが生成されたときに書き込まれると,関数の返却値は文字列型になります. 応用:例えば,戦略は,異なる賃貸者のための資産制限を行う必要があります. 注: 戦略トークンが生成されたとき,Metaストラテジー・トークンが生成されたときにソースデータが設定されていない場合,GetMeta()NULL を返します.

申請によって示された関連情報

function main() {
    // The largest assets value of quote currency allowed by the strategy
    
    // Get the metadata generated when the strategy token is established
    var level = GetMeta()
    
    // Check the corresponding conditions of "Meta"
    if (level == "level1") {
        // "-1" indicates no limitation 
        maxBaseCurrency = -1       
    } else if (level == "level2") {
        maxBaseCurrency = 10     
    } else if (level == "level3") {
        maxBaseCurrency = 1
    } else {
        maxBaseCurrency = 0.5
    }
    
    while(1) {
        Sleep(1000)
        var ticker = exchange.GetTicker()
        
        // Check the assets value
        var acc = exchange.GetAccount()
        if (maxBaseCurrency != -1 && maxBaseCurrency < acc.Stocks + acc.FrozenStocks) {
            // Stop the execution of the strategy trading logic 
            LogStatus(_D(), "level:", level, "The position exceeds the strategy token's using limitation, and stop the execution of the strategy trading logic!")
            continue
        }
        
        // Other trading logic
        
        // Export the information of status bar normally
        LogStatus(_D(), "level:", level, "The strategy runs normally! Ticker data: \n", ticker)
    }
}
def main():
    maxBaseCurrency = null
    level = GetMeta()
    
    if level == "level1":
        maxBaseCurrency = -1       
    elif level == "level2":
        maxBaseCurrency = 10     
    elif level == "level3":
        maxBaseCurrency = 1
    else:
        maxBaseCurrency = 0.5
    
    while True:
        Sleep(1000)
        ticker = exchange.GetTicker()        
        acc = exchange.GetAccount()
        if maxBaseCurrency != -1 and maxBaseCurrency < acc["Stocks"] + acc["FrozenStocks"]:
            LogStatus(_D(), "level:", level, "The position exceeds the strategy token's using limitation, and stop the execution of the strategy trading logic!")
            continue        
        
        # Other trading logic
        
        # Export the information of status bar normally
        LogStatus(_D(), "level:", level, "The strategy runs normally! Ticker data: \n", ticker)
void main() {
    auto maxBaseCurrency = 0.0;
    auto level = GetMeta();
    
    if (level == "level1") {
        maxBaseCurrency = -1;  
    } else if (level == "level2") {
        maxBaseCurrency = 10;
    } else if (level == "level3") {
        maxBaseCurrency = 1;
    } else {
        maxBaseCurrency = 0.5;
    }
    
    while(1) {
        Sleep(1000);
        auto ticker = exchange.GetTicker();  
        auto acc = exchange.GetAccount();
        if (maxBaseCurrency != -1 && maxBaseCurrency < acc.Stocks + acc.FrozenStocks) {
            // Stop the execution of the strategy trading logic
            LogStatus(_D(), "level:", level, "The position exceeds the strategy token's using limitation, and stop the execution of the strategy trading logic!");
            continue;
        }
        
        // Other trading logic
        
        // Export the information of status bar normally
        LogStatus(_D(), "level:", level, "The strategy runs normally! Ticker data: \n", ticker);
    }
}

ダイヤルして...

Dial(Address, Timeout)オリジナルのソケット アクセス,サポートtcp, udp, tlsそしてunixパラメータ値:Address文字列の種類です. 単位は秒です. 時間が終了した場合,関数Dial(...)返される値は空です.

詳細な説明Addressパラメータ:

パラメータ詳細
機能を設定するパラメータDial 追加して分離する|通常の住所の後ろの記号:wss://ws.okx.com:8443/ws/v5/public■ もし,ある場合|パラメータ文字列の文字,使用||各パラメータを&ss5のプロキシと圧縮パラメータを一緒に設定します.Dial("wss://ws.okx.com:8443/ws/v5/public|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv").
ws プロトコルでは,データ圧縮に関するパラメータは:compress=parameter value 圧縮は圧縮方法であり,圧縮パラメータは,gzip_rawそしてgzipgzip 方法が標準でない場合は,拡張方法を使用できます:gzip_raw設定を追加します.compress=gzip_raw隔離器の後ろに|,そして,&シンボルと次のモードパラメータを分離します.
ws プロトコルでは,データ圧縮に関するパラメータは:mode=parameter value 3つのオプションを含むモードです.dual, sendそしてrecv. dual圧縮データを送信し受信する双方向ですsend圧縮されたデータを送信しますrecv圧縮されたデータを受信し 局所的に解圧します
靴下の設定に関する関連パラメータ5 代替:proxy=parameter value proxy は ss5 プロキシ設定です パラメータ値形式:socks5://name:pwd@192.168.0.1:1080nameは ss5 サーバのユーザー名. pwdは ss5 サーバのログインパスワード. 1080は ss5 サーバのポートです.
ws プロトコルでは,基礎的な自動再接続を設定するための関連パラメータ:reconnect=parameter value "再接続"は"再接続"を設定するかどうかを意味します.reconnect=true再接続を呼び出すこと. 既定設定は再接続しないこと.
ws プロトコルでは,基礎的な自動再接続を設定するための関連パラメータ:interval=parameter value "interval"は"millisecond"で再試行する間隔です.interval=1000010秒の再試行間隔で,デフォルト設定は1秒,つまりinterval=1000.
ws プロトコルでは,基礎的な自動再接続を設定するための関連パラメータ:payload= parameter value 便乗は,WSが再接続するときに送られるサブスクリプションメッセージです.例えば:payload=okok.
function main(){
    // Dial supports tcp://, udp://, tls://, unix:// protocol, so you can add a parameter to specify the number of seconds to timeout
    var client = Dial("tls://www.baidu.com:443")  
    if (client) {
        // "Write" can be followed by a numeric parameter to specify the timeout, and "write" returns the number of bytes successfully sent
        client.write("GET / HTTP/1.1\nConnection: Closed\n\n")
        while (true) {
            // "Read" can be followed by a numeric parameter to specify the timeout, in millisecond. Return null to indicate error, timeout or closed socket
            var buf = client.read()
            if (!buf) {
                 break
            }
            Log(buf)
        }
        client.close()
    }
}
def main():
    client = Dial("tls://www.baidu.com:443")
    if client:
        client.write("GET / HTTP/1.1\nConnection: Closed\n\n")
        while True:
            buf = client.read()
            if not buf:
                break
            Log(buf)
        client.close()
void main() {
    auto client = Dial("tls://www.baidu.com:443");
    if(client.Valid) {
        client.write("GET / HTTP/1.1\nConnection: Closed\n\n");
        while(true) {
            auto buf = client.read();
            if(buf == "") {
                break;
            }
            Log(buf);
        }
        client.close();
    }
}

機能についてread次のパラメータに対応します.

  • パラメータが渡されない場合, メッセージが出るまでブロックします.ws.read().
  • パラメータを入力するときは,待機メッセージのタイムアウトをミリ秒単位で指定します.例えば:ws.read(2000)タイムアウトを2秒 (2000ミリ秒) と指定する.
  • 次の2つのパラメータは,websocketについて パラメーターの転送-1メッセージがあるかどうかにかかわらず即座に返信することを意味しますws.read(-1)- わかった パラメーターの転送-2メッセージがあるかどうかにかかわらず即座に返信する.しかし,最新のメッセージのみが返信され,バッファ内のメッセージは捨てられます.ws.read(-2).

機能についてread()バッファの記述: WS プロトコルによって送られるデータが戦略間の長い間隔である場合read()バッファのデータ構造は,2000を上限とするキューである.2000を超えた後,最新のデータがバッファに入力され,最も古いデータはクリアされる.

シナリオRead機能パラメータ パラメーターなし パラメータ: -1 パラメーター: -2 パラメータ: 2000 (単位: ms)
バッファーは既にデータを持っています. 最古のデータをすぐに返します. 最古のデータをすぐに返します. 最新のデータをすぐに返してください. 最古のデータをすぐに返します.
バッファーにデータがない ブロックされたデータがある場合にデータを返す すぐに null を返します すぐに null を返します データがない場合は null を返し,データがある場合はデータを返します.
Ws接続が切断されるか,下層層が再接続される read()関数は null を返します.つまり: ,および関数 write() は 0 を返します.この状況が検出された場合,関数 close() を使用して接続を終了できます.自動再接続を設定した場合,閉鎖する必要はありません.システムの底層は自動的に再接続されます.
  • Wss (WebSocket) プロトコルをサポート バイナンスウェブソケット市場インターフェイスにアクセス:

    function main() {
        LogStatus("connecting...")
        // Access Binance websocket interface
        var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
        if (!client) {
            Log("connection failed, program exited")
            return
        }
        
        while (true) {
            // "read" only returns the obtained data after call "read" 
            var buf = client.read()      
            if (!buf) {
                break
            }
            var table = {
                type: 'table',
                title: 'Quote Chart',
                cols: ['Currency', 'Highest', 'Lowest', 'Buy One', 'Sell One', 'Last Executed Price', 'Volume', 'Update Time'],
                rows: []
            }
            var obj = JSON.parse(buf)
            _.each(obj, function(ticker) {
                table.rows.push([ticker.s, ticker.h, ticker.l, ticker.b, ticker.a, ticker.c, ticker.q, _D(ticker.E)])
            })
            LogStatus('`' + JSON.stringify(table) + '`')
        }
        client.close()
    }
    
    import json
    def main():
        LogStatus("connecting...")
        client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
        if not client:
            Log("Connection failed, program exited")
            return 
        
        while True:
            buf = client.read()
            if not buf:
                break
            table = {
                "type" : "table", 
                "title" : "Quote Chart", 
                "cols" : ['Currency', 'Highest', 'Lowest', 'Buy One', 'Sell One', 'Last Executed Price', 'Volume', 'Update Time'], 
                "rows" : [] 
            }
            obj = json.loads(buf)
            for i in range(len(obj)):
                table["rows"].append([obj[i]["s"], obj[i]["h"], obj[i]["l"], obj[i]["b"], obj[i]["a"], obj[i]["c"], obj[i]["q"], _D(int(obj[i]["E"]))])
            LogStatus('`' + json.dumps(table) + '`')
        client.close()
    
    void main() {
        LogStatus("connecting...");
        auto client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr");
        if(!client.Valid) {
            Log("Connection failed, program exited");
            return;
        }
        
        while(true) {
            auto buf = client.read();
            if(buf == "") {
                break;
            }
            json table = R"({
                "type" : "table", 
                "title" : "Quote Chart", 
                "cols" : ['Currency', 'Highest', 'Lowest', 'Buy One', 'Sell One', 'Last Executed Price', 'Volume', 'Update Time'], 
                "rows" : []
            })"_json;
            json obj = json::parse(buf);
            for(auto& ele : obj.items()) {
                table["rows"].push_back({ele.value()["s"], ele.value()["h"], ele.value()["l"], ele.value()["b"], ele.value()["a"], ele.value()["c"], 
                    ele.value()["q"], _D(ele.value()["E"])});
            }
            LogStatus("`" + table.dump() + "`");
        }
        client.close();
    }
    

    アクセス OKX Webソケット市場インターフェース:

    var ws = null 
    function main(){
          var param = {
            "op": "subscribe",
            "args": [{
                "channel": "tickers",
                "instId": "BTC-USDT"
            }]
        }
        // When call the function "Dial", specify "reconnect=true" and set to reconnect; specify "payload" as the message to be sent when reconnect. When websocket closes the connection, it will automatically reconnect and send the message
        ws = Dial("wss://ws.okx.com:8443/ws/v5/public|compress=gzip_raw&mode=recv&reconnect=true&payload="+ JSON.stringify(param))
        if(ws){
            ws.write(JSON.stringify(param))
            var pingCyc = 1000 * 20
            var lastPingTime = new Date().getTime()
            while(true){
                var nowTime = new Date().getTime()
                var ret = ws.read()
                Log("ret:", ret)
                if(nowTime - lastPingTime > pingCyc){
                    var retPing = ws.write("ping")
                    lastPingTime = nowTime
                    Log("send: ping", "#FF0000")
                }
                LogStatus("current time:", _D())
                Sleep(1000)
            }
        }
    }
    
    function onexit() {
        ws.close() 
        Log("exit")
    }
    
    import json
    import time
    
    ws = None
    def main():
        global ws 
        param = {
            "op": "subscribe",
            "args": [{
                "channel": "tickers",
                "instId": "BTC-USDT"
            }]
        }
        ws = Dial("wss://ws.okx.com:8443/ws/v5/public|compress=gzip_raw&mode=recv&reconnect=true&payload=" + json.dumps(param))
        if ws:
            pingCyc = 1000 * 20
            lastPingTime = time.time() * 1000
            while True:
                nowTime = time.time() * 1000
                ret = ws.read()
                Log("ret:", ret)
                if nowTime - lastPingTime > pingCyc:
                    retPing = ws.write("ping")
                    lastPingTime = nowTime
                    Log("send: ping", "#FF0000")
                LogStatus("current time:", _D())
                Sleep(1000)
    
    def onexit():
        ws.close()
        Log("exit")
    
    auto objWS = Dial("wss://ws.okx.com:8443/ws/v5/public|compress=gzip_raw&mode=recv&reconnect=true");  
    
    void main() {
            json param = R"({"op": "subscribe", "args": ["spot/ticker:ETH-USDT"]})"_json;
             "op": "subscribe",
            "args": [{
                "channel": "tickers",
                "instId": "BTC-USDT"
            }]
        })"_json;
        
        objWS.write(param.dump());
        if(objWS.Valid) {
            uint64_t pingCyc = 1000 * 20;
            uint64_t lastPingTime = Unix() * 1000;
            while(true) {
                uint64_t nowTime = Unix() * 1000;
                auto ret = objWS.read();
                Log("ret:", ret);
                if(nowTime - lastPingTime > pingCyc) {
                    auto retPing = objWS.write("ping");
                    lastPingTime = nowTime;
                    Log("send: ping", "#FF0000");
                }
                LogStatus("current time:", _D());
                Sleep(1000);
            }
        }
    }  
    
    void onexit() {
        objWS.close();
        Log("exit");
    }
    

    Huobi Webソケット市場インターフェイスにアクセス:

    var ws = null   
    
    function main(){
        var param = {"sub": "market.btcusdt.detail", "id": "id1"}
        ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload="+ JSON.stringify(param))
        if(ws){
            while(1){
                var ret = ws.read()
                Log("ret:", ret)
                // Respond to heartbeat
                try {
                    var jsonRet = JSON.parse(ret)
                    if(typeof(jsonRet.ping) == "number") {
                        var strPong = JSON.stringify({"pong" : jsonRet.ping})
                        ws.write(strPong)
                        Log("respond ping, send pong:", strPong, "#FF0000")
                    }
                } catch(e) {
                    Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
                }
                
                LogStatus("current time:", _D())
                Sleep(1000)
            }
        }
    }  
    
    function onexit() {
        ws.close() 
        Log("execute function ws.close()")
    }
    
    import json
    ws = None  
    
    def main():
        global ws
        param = {"sub" : "market.btcusdt.detail", "id" : "id1"}
        ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload=" + json.dumps(param))
        if ws:
            while True:
                ret = ws.read()
                Log("ret:", ret)              
                # Respond to heartbeat 
                try:
                    jsonRet = json.loads(ret)
                    if "ping" in jsonRet and type(jsonRet["ping"]) == int:
                        strPong = json.dumps({"pong" : jsonRet["ping"]})
                        ws.write(strPong)
                        Log("respond ping, send pong:", strPong, "#FF0000")
                except Exception as e:
                    Log("e:", e)
                    
                LogStatus("current time: ", _D())
                Sleep(1000)
        
    def onexit():
        ws.close()
        Log("execute function ws.close()")  
    
    using namespace std;
    void main() {
        json param = R"({"sub" : "market.btcusdt.detail", "id" : "id1"})"_json;
        auto ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload=" + param.dump());
        if(ws.Valid) {
            while(true) {
                auto ret = ws.read();
                Log("ret:", ret);              
                // Respond to heartbeat
                try 
                {
                    auto jsonRet = json::parse(ret);
                    if(jsonRet["ping"].is_number()) {
                        json pong = R"({"pong" : 0})"_json;
                        pong["pong"] = jsonRet["ping"];
                        auto strPong = pong.dump();
                        ws.write(strPong);
                        Log("respond ping, send pong:", strPong, "#FF0000");
                    }
                } catch(exception &e) 
                {
                    Log("e:", e.what());
                }
                
                LogStatus("current time:", _D());
                Sleep(1000);
            }
        }
    }  
    
    void onexit() {
        // ws.close();
        Log("execute function ws.close()");
    }
    

    OKX にアクセスする webソケット インターフェースの検証 インターフェース:

      function getLogin(pAccessKey, pSecretKey, pPassphrase) {
        // Signature function for login
        var ts = (new Date().getTime() / 1000).toString()
        var login = {
            "op": "login",
            "args":[{
                "apiKey"    : pAccessKey,
                "passphrase" : pPassphrase,
                "timestamp" : ts,
                "sign" : exchange.HMAC("sha256", "base64", ts + "GET" + "/users/self/verify", pSecretKey)
            }]
        }    
        return login
    }    
    
    var client_private = null 
    function main() {
        // Because the read function adopts the timeout setting, the timeout error is filtered, otherwise there will be redundant error output
        SetErrorFilter("timeout")
        
        // Position channel subscription information
        var posSubscribe = {
            "op": "subscribe",
            "args": [{
                "channel": "positions",
                "instType": "ANY"
            }]
        }    
    
        var accessKey = "xxx"
        var secretKey = "xxx"
        var passphrase = "xxx"
    
        client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
        client_private.write(JSON.stringify(getLogin(accessKey, secretKey, passphrase)))
        Sleep(3000)  // When logging in, we cannot subscribe to private channels immediately, we need to wait for server response
        client_private.write(JSON.stringify(posSubscribe))
        if (client_private) {
            var lastPingTS = new Date().getTime()
            while (true) {
                var buf = client_private.read(-1)
                if (buf) {
                    Log(buf)
                }
                
                // Detect disconnection, reconnect
                if (buf == "" && client_private.write(JSON.stringify(posSubscribe)) == 0) {
                    Log("Disconnection detected, connection closed, reconnect")
                    client_private.close()
                    client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
                    client_private.write(JSON.stringify(getLogin(accessKey, secretKey, passphrase)))
                    Sleep(3000)
                    client_private.write(JSON.stringify(posSubscribe))
                }
                
                // Send heartbeat packets
                var nowPingTS = new Date().getTime()
                if (nowPingTS - lastPingTS > 10 * 1000) {
                    client_private.write("ping")
                    lastPingTS = nowPingTS
                }            
            }        
        }
    }    
    
    function onexit() {    
        var ret = client_private.close()
        Log("Close the connection!", ret)
    }
    
    import json
    import time
        
    def getLogin(pAccessKey, pSecretKey, pPassphrase):
        ts = str(time.time())
        login = {
            "op": "login",
            "args":[{
                "apiKey"    : pAccessKey,
                "passphrase" : pPassphrase,
                "timestamp" : ts,
                "sign" : exchange.HMAC("sha256", "base64", ts + "GET" + "/users/self/verify", pSecretKey)
            }]
        }
        return login     
    
    client_private = None 
    def main():
        global client_private
        SetErrorFilter("timeout")
        
        posSubscribe = {
            "op": "subscribe",
            "args": [{
                "channel": "positions",
                "instType": "ANY"
            }]
        }      
    
        accessKey = "xxx"
        secretKey = "xxx"
        passphrase = "xxx"
        
        client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
        client_private.write(json.dumps(getLogin(accessKey, secretKey, passphrase)))
        Sleep(3000)
        client_private.write(json.dumps(posSubscribe))
        if client_private:
            lastPingTS = time.time() * 1000
            while True:
                buf = client_private.read(-1)
                if buf:
                    Log(buf)
                
                if buf == "" and client_private.write(json.dumps(posSubscribe)) == 0:
                    Log("Disconnection detected, connection closed, reconnect")
                    ret = client_private.close()
                    client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
                    client_private.write(json.dumps(getLogin(accessKey, secretKey, passphrase)))
                    Sleep(3000)
                    client_private.write(json.dumps(posSubscribe))
                
                nowPingTS = time.time() * 1000
                if nowPingTS - lastPingTS > 10 * 1000:
                    client_private.write("ping")
                    lastPingTS = nowPingTS    
    
    def onexit():
        ret = client_private.close()
        Log("Close the connection!", ret)
    

auto client_private = ダイヤル (※)

JSON getLogin ((文字列 pAccessKey,文字列 pSecretKey,文字列 pPassphrase) { auto ts = std::to_string (ユニックス) JSON ログイン = R"({ op: ログイン, ARGS: [{ apiKey: , パスワード: , 時間スタンプ: サイン: {a1pos (110,268) } }) "_json; login[args][0][apiKey] = pAccessKey; login[args][0][passphrase] = pPassphrase; パスフレーズ login[args][0][タイムスタンプ] = ts; login[args][0][sign] = exchange.HMAC ((sha256, base64, ts + GET + /users/self/verify, pSecretKey); リターン ログイン { \ pos (192,220) }

メインは空です. SetErrorFilter ((タイムアウト); Json pos サブスクリプション = R"({ op: 登録, ARGS: [{ チャンネル: ポジション, instType: ANY {a1pos (110,268) } }) "_json;

auto accessKey = "xxx";
auto secretKey = "xxx";
auto passphrase = "xxx";

client_private.write(getLogin(accessKey, secretKey, passphrase).dump());
Sleep(3000);
client_private.write(posSubscribe.dump());  

if (client_private.Valid) {
    uint64_t lastPingTS = Unix() * 1000;    

    while (true) {
        auto buf = client_private.read(-1);
        if (buf != "") {
            Log(buf);
        }
        if (buf == "") {
            if (client_private.write(posSubscribe.dump()) == 0) {
                Log("Disconnection detected, connection closed, reconnect");
                client_private.close();
                client_private = Dial("wss://ws.okx.com:8443/ws/v5/private");
                client_private.write(getLogin(accessKey, secretKey, passphrase).dump());
                Sleep(3000);
                client_private.write(posSubscribe.dump());
            }
        }
        
        uint64_t nowPingTS = Unix() * 1000;
        if (nowPingTS - lastPingTS > 10 * 1000) {
            client_private.write("ping");
            lastPingTS = nowPingTS;
        }
    }
}

}

無効で終了する client_private.close (クライアント_プライベート.クローズ) ログ (出口) { \ pos (192,220) }


#### HttpQuery(...)

```HttpQuery(Url, PostData, Cookies, Headers, IsReturnHeader)``` is an access of web URL. Parameter value: all are of string types.

Note:
* The ```HttpQuery(...)``` function only supports ```JavaScript``` language.
* For the ```Python``` language, you can use ```urllib``` to send http requests directly.

```HttpQuery(...)``` is mainly used to access the exchange interfaces that do not require signatures, such as public interfaces including market information.
An example of an API that does not require a signature to access OKX: the return value is a ```JSON``` string, which can be parsed by using the function ```JSON.parse()``` in JavaScript language strategies.

```js
function main(){
  // An example of GET access without parameters
  var info = JSON.parse(HttpQuery("https://www.okx.com/api/v5/public/time"))
  Log(info)
  // An example of GET access with parameters
  var ticker = JSON.parse(HttpQuery("https://www.okx.com/api/v5/market/books?instId=BTC-USDT"))
  Log(ticker)
}
import json
import urllib.request
def main():
    # HttpQuery does not support Python, you can use urllib/urllib2 instead
    info = json.loads(urllib.request.urlopen("https://www.okx.com/api/v5/public/time").read().decode('utf-8'))
    Log(info)
    ticker = json.loads(urllib.request.urlopen("https://www.okx.com/api/v5/market/books?instId=BTC-USDT").read().decode('utf-8'))
    Log(ticker)
void main() {
    auto info = json::parse(HttpQuery("https://www.okx.com/api/v5/public/time"));
    Log(info);
    auto ticker = json::parse(HttpQuery("https://www.okx.com/api/v5/market/books?instId=BTC-USDT"));
    Log(ticker);
}

2番目のパラメータが表示される場合PostData文字列の形をしているa=1&b=2&c=abc提出するPOSTほかにはPUT■ パラメータPostData{method:'PUT', data:'a=1&b=2&c=abc'}.

についてPostDataパラメータもJSON string.

パラメータの形式Cookiesこれは:a=10; b=20; 各パラメータはセミコンロンで区切られる;- わかった パラメータの形式Headersこれは:User-Agent: Mobile\nContent-Type: text/html; 各パラメータは新行文字で区切られる\n.

2つ目のパラメータはPostDataパーソナライズできます 例えば:HttpQuery("http://www.abc.com", {method:'PUT', data:'a=1&b=2&c=abc'})タイムアウトを設定する必要がある場合HttpQueryこの関数にtimeout属性{method:'put',data:'a=1&B=2&C=ABC'}(デフォルトは60秒)

1秒間のタイムアウトを設定するHttpQuery("http://www.abc.com", {method:'PUT', data:'a=1&b=2&c=abc', timeout:1000})

文字列を通すには3番目のパラメータが必要です.CookieでもPOST第2パラメータを null に設定する必要はありません. シミュレーションテスト中に,URLをシミュレートできないので,関数は固定文字列を返します.Dummy Data. このインターフェースを使用してテキストメッセージを送信したり,他の API インターフェースとやり取りしたりできます.

GETメソッド呼び出し例:HttpQuery("http://www.baidu.com"). POSTメソッド呼び出し例:HttpQuery("http://www.163.com", "a=1&b=2&c=abc").

呼び出しの返信の例Header:

HttpQuery("http://www.baidu.com", null, "a=10; b=20", "User-Agent: Mobile\nContent-Type: text/html", true)  // will return {Header: HTTP Header, Body: HTML}
  • 機能についてHttpQueryプロキシ設定を使用します:

    function main() {
        // This time, set proxy and send http request; without username and password, this http request will be sent through the proxy
        HttpQuery("socks5://127.0.0.1:8889/http://www.baidu.com/")
    
        // Set the proxy and send http request this time, enter the user name and password, only the current call of HttpQuery takes effect, then call HttpQuery ("http://www.baidu.com") again so that the proxy will not be used
        HttpQuery("socks5://username:password@127.0.0.1:8889/http://www.baidu.com/")
    }
    
    # If HttpQuery does not support Python, you can use Python urllib2 library
    
    void main() {
        HttpQuery("socks5://127.0.0.1:8889/http://www.baidu.com/");
        HttpQuery("socks5://username:password@127.0.0.1:8889/http://www.baidu.com/");
    }
    
  • 機能についてHttpQueryアシンクロンバージョンですHttpQuery_Goについて 機能と類似している.exchange.Go取引所の公開インターフェイスに非同期的にアクセスして,市場データを集計するなど.

    function main() {
        // Set up the first asyncthread
        var r1 = HttpQuery_Go("https://www.okx.com/api/v5/market/tickers?instType=SPOT")
        // Set up the second asyncthread
        var r2 = HttpQuery_Go("https://api.huobi.pro/market/tickers")
        
        // Get the return value of the first asyncthread
        var tickers1 = r1.wait()
        // Get the return value of the second asyncthread
        var tickers2 = r2.wait()
        
        // Print result
        Log("tickers1:", tickers1)
        Log("tickers2:", tickers2)
    }
    
    # Not supported
    
    // Not supported
    
  • 機能の使用HttpQuery(...)バックテストシステムでは: データを入手するには,HttpQuery(...)申請を送信する (サポートのみ)GETバックテストで20回制限を課し,HttpQuery(...)機能が表示される間,HttpQuery(...)同じURLへの2度目のアクセスでキャッシュされたデータを返します (実際のWebリクエストは不要です)

    サーバやデバイスで実行できます.HttpQuery(...)戦略プログラムで,テスト用のGo言語のサービスプログラムが示されています.

    package main
    import (
        "fmt"
        "net/http"
        "encoding/json"
    )
    
    func Handle (w http.ResponseWriter, r *http.Request) {
        defer func() {
            fmt.Println("req:", *r)
            ret := map[string]interface{}{
                "schema" : []string{"time","open","high","low","close","vol"},
                "data" : []interface{}{
                    []int64{1564315200000,9531300,9531300,9497060,9497060,787},
                    []int64{1564316100000,9495160,9495160,9474260,9489460,338},
                },
            }
            b, _ := json.Marshal(ret)
            w.Write(b)
        }()
    }
    
    func main () {
        fmt.Println("listen http://localhost:9090")
        http.HandleFunc("/data", Handle)
        http.ListenAndServe(":9090", nil)
    }
    

    この関数を使うHttpQuery(...)戦略バックテスト中にリクエストを送信する:

    function main() {
        // You can write the IP address of the device where the service program is run
        Log(HttpQuery("http://xxx.xx.x.xxx:9090/data?msg=hello"));
        Log(exchange.GetAccount());
    }
    
    # If HttpQuery does not support Python, you can use Python urllib2 library
    
    void main() {
        //  You can write the IP address of the device where the service program is run
        Log(HttpQuery("http://xxx.xx.x.xxx:9090/data?msg=hello"));
        Log(exchange.GetAccount());
    }
    

    img

    リクエストの応答データのトランスコード化もサポートし,一般的なコーディングもサポートします. 特定するPostDataパラメータ:{method: "GET", charset: "GB18030"}応答データトランスコード (GB18030) を実現できる.

暗号化する

Encode(algo, inputFormat, outputFormat, data, keyFormat, key string), この関数は,渡されたパラメータに従ってデータをコードし,文字列値を返します.

パラメータalgo暗号化計算に使用されるアルゴリズムで,以下に設定できる: raw (アルゴリズムなし), sign, signTx, md4, md5, sha256, sha512, sha1, keccak256, sha3.224, sha3.256, sha3.384, sha3.512, sha3.keccak256, sha3.keccak512, sha512.384, sha512.256, sha512.224, emd160, blake2rip2b.256, blake2b.512, blake2s.1288, blake2s.256 パラメーター.data処理するデータです.inputFormat/outputFormat/keyFormatパラメータは,以下のようなコード化方法をサポートします.raw, hex, base64そしてstring- わかった もしkeyFormatパラメータが空でない場合,keyパラメータは暗号化 (HMAC) に使用されます.key` ` ⌒ ⌒ ⌒ ⌒ ⌒ ⌒ ⌒ ⌒ ⌒ ⌒