4
ध्यान केंद्रित करना
1271
समर्थक

इन्वेंटर क्वांटिटेटिव ट्रेडिंग प्लेटफॉर्म जनरल प्रोटोकॉल एक्सेस गाइड

में बनाया: 2024-10-29 14:37:56, को अपडेट: 2024-11-12 21:58:55
comments   0
hits   865

[TOC]

इन्वेंटर क्वांटिटेटिव ट्रेडिंग प्लेटफॉर्म जनरल प्रोटोकॉल एक्सेस गाइड

इन्वेंटर क्वांटिटेटिव ट्रेडिंग प्लेटफॉर्म कई क्रिप्टोकरेंसी एक्सचेंजों का समर्थन करता है और बाजार में मुख्यधारा के एक्सचेंजों को समाहित करता है। हालाँकि, अभी भी कई ऐसे एक्सचेंज हैं जो पैकेज्ड नहीं हैं। जिन उपयोगकर्ताओं को इन एक्सचेंजों का उपयोग करने की आवश्यकता है, वे आविष्कारक द्वारा निर्धारित सार्वभौमिक प्रोटोकॉल के माध्यम से उन तक पहुँच सकते हैं। क्रिप्टोकरेंसी एक्सचेंजों तक सीमित नहीं, कोई भीRESTसमझौता याFIXसमझौते के प्लेटफॉर्म तक भी पहुंचा जा सकता है।

यह लेखRESTप्रोटोकॉल एक्सेस को एक उदाहरण के रूप में लेते हुए, यह बताता है कि OKX एक्सचेंज के API को समाहित करने और उस तक पहुंचने के लिए इन्वेंटर क्वांटिटेटिव ट्रेडिंग प्लेटफॉर्म के सामान्य प्रोटोकॉल का उपयोग कैसे किया जाए। जब तक अन्यथा निर्दिष्ट न किया जाए, यह आलेख REST सामान्य प्रोटोकॉल को संदर्भित करता है।

  • सामान्य प्रोटोकॉल का कार्यप्रवाह इस प्रकार है: अनुरोध प्रक्रिया: कस्टोडियन पर चल रही रणनीति इंस्टेंस -> सामान्य प्रोटोकॉल प्रोग्राम -> एक्सचेंज एपीआई प्रतिक्रिया प्रक्रिया: एक्सचेंज एपीआई -> सामान्य प्रोटोकॉल प्रोग्राम -> कस्टोडियन पर चल रहा रणनीति उदाहरण

1. एक्सचेंज को कॉन्फ़िगर करें

इन्वेंटर क्वांटिटेटिव ट्रेडिंग प्लेटफॉर्म पर एक्सचेंज को कॉन्फ़िगर करने के लिए पेज:

https://www.fmz.com/m/platforms/add

इन्वेंटर क्वांटिटेटिव ट्रेडिंग प्लेटफॉर्म जनरल प्रोटोकॉल एक्सेस गाइड

  • प्रोटोकॉल चुनें: “सामान्य प्रोटोकॉल” चुनें.
  • सेवा पता: सामान्य प्रोटोकॉल प्रोग्राम अनिवार्य रूप से एक RPC सेवा है इसलिए, एक्सचेंज को कॉन्फ़िगर करते समय सेवा पता और पोर्ट को स्पष्ट रूप से निर्दिष्ट करना आवश्यक है। अतः इसमें托管者上运行的策略实例 -> 通用协议程序प्रक्रिया के दौरान, होस्ट को पता होता है कि सामान्य प्रोटोकॉल प्रोग्राम तक कहां पहुंचना है। उदाहरण के लिए:http://127.0.0.1:6666/OKXआमतौर पर, सामान्य प्रोटोकॉल प्रोग्राम और होस्ट एक ही डिवाइस (सर्वर) पर चलाए जाते हैं, इसलिए सेवा पता स्थानीय मशीन (लोकलहोस्ट) के रूप में लिखा जाता है, और पोर्ट वह पोर्ट हो सकता है जो सिस्टम द्वारा कब्जा नहीं किया जाता है।
  • Access Key: 托管者上运行的策略实例 -> 通用协议程序प्रक्रिया के दौरान पारित की गई एक्सचेंज कॉन्फ़िगरेशन जानकारी.
  • Secret Key: 托管者上运行的策略实例 -> 通用协议程序प्रक्रिया के दौरान पारित की गई एक्सचेंज कॉन्फ़िगरेशन जानकारी.
  • लेबल: इन्वेंटर क्वांटिटेटिव ट्रेडिंग प्लेटफॉर्म पर एक्सचेंज ऑब्जेक्ट लेबल का उपयोग किसी निश्चित एक्सचेंज ऑब्जेक्ट की पहचान करने के लिए किया जाता है।

लेख में बताए गए OKX प्लग-इन कॉन्फ़िगरेशन का स्क्रीनशॉट इस प्रकार है:

इन्वेंटर क्वांटिटेटिव ट्रेडिंग प्लेटफॉर्म जनरल प्रोटोकॉल एक्सेस गाइड

OKX एक्सचेंज गुप्त कुंजी कॉन्फ़िगरेशन जानकारी:

accessKey:  accesskey123    // accesskey123 这些并不是实际秘钥,仅仅是演示
secretKey:  secretkey123
passphrase: passphrase123

2. कस्टोडियन और यूनिवर्सल प्रोटोकॉल प्रोग्राम (प्लगइन) की तैनाती

    1. मेज़बान इन्वेंटर क्वांटिटेटिव ट्रेडिंग प्लेटफ़ॉर्म पर किसी भी वास्तविक समय की रणनीति को चलाने के लिए, आपको एक कस्टोडियन तैनात करना होगा। कस्टोडियन की विशिष्ट तैनाती के लिए, कृपया प्लेटफ़ॉर्म ट्यूटोरियल देखें, जिसे यहाँ दोहराया नहीं जाएगा।
    1. सामान्य प्रोटोकॉल प्रोग्राम (प्लगइन) होस्ट और यूनिवर्सल प्रोटोकॉल आमतौर पर एक ही डिवाइस पर तैनात किए जाते हैं। यूनिवर्सल प्रोटोकॉल (सेवा) प्रोग्राम किसी भी भाषा में लिखा जा सकता है। यह लेख पायथन 3 में लिखा गया है। किसी भी पायथन प्रोग्राम को चलाने की तरह, आप इसे सीधे निष्पादित कर सकते हैं (पायथन वातावरण के विभिन्न कॉन्फ़िगरेशन पहले से बना सकते हैं)। बेशक, FMZ पायथन प्रोग्राम चलाने का भी समर्थन करता है, और इस सामान्य प्रोटोकॉल को आविष्कारक के मात्रात्मक ट्रेडिंग प्लेटफॉर्म को अनपैक्ड एक्सचेंज API एक्सेस के लिए समर्थन प्रदान करने के लिए एक वास्तविक डिस्क के रूप में चलाया जा सकता है। सामान्य प्रोटोकॉल प्रोग्राम चलने के बाद, निगरानी शुरू करें:http://127.0.0.1:6666सामान्य प्रोटोकॉल प्रोग्राम में, विशिष्ट पथ निर्दिष्ट किए जा सकते हैं, उदाहरण के लिए/OKXसंसाधित किया जाना है।

3. रणनीति उदाहरण FMZ API फ़ंक्शन का अनुरोध करता है

जब रणनीति में (FMZ) प्लेटफ़ॉर्म API फ़ंक्शन को कॉल किया जाता है, तो यूनिवर्सल प्रोटोकॉल प्रोग्राम कस्टोडियन से अनुरोध प्राप्त करता है। आप प्लेटफ़ॉर्म के डिबगिंग टूल का उपयोग करके भी परीक्षण कर सकते हैं, उदाहरण के लिए:

डिबगिंग उपकरण पृष्ठ:

https://www.fmz.com/m/debug

function main() {
    return exchange.GetTicker("LTC_USDT")
}

पुकारनाexchange.GetTicker()फ़ंक्शन, सामान्य प्रोटोकॉल प्रोग्राम अनुरोध प्राप्त करता है:

POST /OKX HTTP/1.1 
{
    "access_key":"xxx",
    "method":"ticker",
    "nonce":1730275031047002000,
    "params":{"symbol":"LTC_USDT"},
    "secret_key":"xxx"
}
  • access_key: ऊपर दिए गए “एक्सचेंज कॉन्फ़िगर करें” प्लेटफ़ॉर्म में कॉन्फ़िगर की गई एक्सचेंज कुंजी
  • secret_key: ऊपर दिए गए “एक्सचेंज कॉन्फ़िगर करें” प्लेटफ़ॉर्म में कॉन्फ़िगर की गई एक्सचेंज कुंजी
  • विधि: रणनीति में कॉलिंग इंटरफ़ेस से संबंधित, कॉलिंगexchange.GetTicker()घंटा,methodवह हैticker
  • नॉन्स: वह टाइमस्टैम्प जब अनुरोध हुआ।
  • पैरामीटर: नीति में इंटरफ़ेस कॉल से संबंधित पैरामीटर.exchange.GetTicker()कॉल करते समय, प्रासंगिक पैरामीटर हैं:{"symbol":"LTC_USDT"}

4. एक्सचेंज इंटरफ़ेस तक सामान्य प्रोटोकॉल प्रोग्राम पहुंच

जब सामान्य प्रोटोकॉल प्रोग्राम कस्टोडियन से अनुरोध प्राप्त करता है, तो वह अनुरोध में दी गई जानकारी के आधार पर रणनीति द्वारा अनुरोधित प्लेटफ़ॉर्म API फ़ंक्शन (पैरामीटर जानकारी सहित), एक्सचेंज कुंजी आदि जैसी जानकारी प्राप्त कर सकता है।

इस जानकारी के आधार पर, सामान्य प्रोटोकॉल प्रोग्राम आवश्यक डेटा प्राप्त करने या कुछ संचालन करने के लिए एक्सचेंज इंटरफ़ेस तक पहुंच सकता है।

आमतौर पर एक्सचेंज इंटरफ़ेस में GET/POST/PUT/DELETE जैसी विधियां होती हैं, जिन्हें सार्वजनिक इंटरफ़ेस और निजी इंटरफ़ेस में विभाजित किया जाता है।

  • सार्वजनिक इंटरफ़ेस: एक इंटरफ़ेस जिसे हस्ताक्षर सत्यापन की आवश्यकता नहीं होती है और जिसे सामान्य प्रोटोकॉल प्रोग्राम में सीधे अनुरोध किया जाता है।
  • निजी इंटरफ़ेस: एक इंटरफ़ेस जिसके लिए हस्ताक्षर सत्यापन की आवश्यकता होती है। इन एक्सचेंजों के API इंटरफ़ेस का अनुरोध करने के लिए हस्ताक्षर को सामान्य प्रोटोकॉल प्रोग्राम में लागू किया जाना चाहिए।

सामान्य प्रोटोकॉल प्रोग्राम एक्सचेंज इंटरफ़ेस प्रतिक्रिया डेटा प्राप्त करता है, इसे आगे संसाधित करता है, और इसे कस्टोडियन द्वारा अपेक्षित डेटा में निर्मित करता है (नीचे वर्णित)। OKX स्पॉट एक्सचेंज, कस्टमप्रोटोकॉलOKX क्लास कार्यान्वयन पायथन सामान्य प्रोटोकॉल उदाहरण देखेंGetTickerGetAccountऔर अन्य कार्य.

5. सामान्य प्रोटोकॉल प्रोग्राम कस्टोडियन को डेटा भेजता है

जब सामान्य प्रोटोकॉल प्रोग्राम एक्सचेंज के API इंटरफ़ेस तक पहुंचता है, कुछ निश्चित ऑपरेशन करता है या कुछ डेटा प्राप्त करता है, तो उसे परिणामों को कस्टोडियन को वापस भेजने की आवश्यकता होती है।

संरक्षक को भेजा गया डेटा रणनीति द्वारा बुलाए गए इंटरफ़ेस के अनुसार भिन्न होता है, और इसे पहले दो श्रेणियों में विभाजित किया जाता है:

  • सामान्य प्रोटोकॉल प्रोग्राम सफलतापूर्वक एक्सचेंज इंटरफ़ेस को कॉल करता है:
  {
      "data": null,  // "data" can be of any type 
      "raw": null    // "raw" can be of any type 
  }
  • डेटा: इस फ़ील्ड की विशिष्ट संरचना सामान्य प्रोटोकॉल प्रोग्राम द्वारा प्राप्त अनुरोध के समान है।methodFMZ प्लेटफ़ॉर्म API फ़ंक्शन द्वारा लौटाए गए डेटा संरचना के निर्माण के लिए उपयोग किए जाने वाले सभी इंटरफेस की सूची निम्नलिखित है।

  • कच्चा: इस फ़ील्ड का उपयोग एक्सचेंज API प्रतिक्रिया के कच्चे डेटा को पास करने के लिए किया जा सकता है, उदाहरण के लिएexchange.GetTicker()फ़ंक्शन द्वारा लौटाई गई टिकर संरचना में टिकर संरचना के जानकारी फ़ील्ड में निम्नलिखित जानकारी दर्ज की गई है:rawफ़ील्ड औरdataफ़ील्ड का डेटा; कुछ प्लेटफ़ॉर्म API फ़ंक्शनों को इस डेटा की आवश्यकता नहीं होती है।

  • सामान्य प्रोटोकॉल प्रोग्राम एक्सचेंज इंटरफ़ेस को कॉल करने में विफल रहा (व्यावसायिक त्रुटि, नेटवर्क त्रुटि, आदि)

  {
      "error": ""    // "error" contains an error message as a string
  }
  • त्रुटि: त्रुटि जानकारी, जो (FMZ) प्लेटफ़ॉर्म वास्तविक डिस्क, डिबगिंग टूल और अन्य पृष्ठों के लॉग क्षेत्र में त्रुटि लॉग में प्रदर्शित की जाएगी।

नीति कार्यक्रम द्वारा प्राप्त सामान्य प्रोटोकॉल प्रतिक्रिया डेटा को प्रदर्शित करता है:

// FMZ平台的调试工具中测试
function main() {
    Log(exchange.GetTicker("USDT"))       // 交易对不完整,缺少BaseCurrency部分,需要通用协议插件程序返回报错信息: {"error": "..."}
    Log(exchange.GetTicker("LTC_USDT"))
}

इन्वेंटर क्वांटिटेटिव ट्रेडिंग प्लेटफॉर्म जनरल प्रोटोकॉल एक्सेस गाइड

6. सामान्य प्रोटोकॉल में डेटा संरचना समझौता

ऊपर सामान्य प्रोटोकॉल प्रोग्राम (FMZ अनपैकेज्ड) एक्सचेंज API तक पहुँचने में कैसे भाग लेता है, इसकी एक संक्षिप्त प्रक्रिया है। यह प्रक्रिया केवल यह बताती है कि (FMZ) प्लेटफ़ॉर्म डिबगिंग टूल को कैसे कॉल किया जाए।exchange.GetTicker()कार्य प्रक्रिया. इसके बाद, सभी प्लेटफ़ॉर्म API फ़ंक्शनों के इंटरैक्शन विवरण को विस्तार से समझाया जाएगा।

यह प्लेटफ़ॉर्म विभिन्न एक्सचेंजों के सामान्य कार्यों को समाहित करता है और उन्हें एक निश्चित फ़ंक्शन में एकीकृत करता है, जैसे कि GetTicker फ़ंक्शन, जो किसी निश्चित उत्पाद की वर्तमान बाज़ार जानकारी का अनुरोध करता है। यह मूल रूप से एक API है जो सभी एक्सचेंजों के पास होता है। इसलिए जब रणनीति इंस्टैंस में प्लेटफ़ॉर्म एनकैप्सुलेटेड API इंटरफ़ेस तक पहुँचा जाता है, तो कस्टोडियन “यूनिवर्सल प्रोटोकॉल” प्लग-इन (ऊपर उल्लिखित) को एक अनुरोध भेजेगा:

POST /OKX HTTP/1.1 
{
    "access_key": "xxx",
    "method": "ticker",
    "nonce": 1730275031047002000,
    "params": {"symbol":"LTC_USDT"},
    "secret_key": "xxx"
}

रणनीति में विभिन्न आविष्कारक प्लेटफ़ॉर्म एनकैप्सुलेटेड API फ़ंक्शनों को कॉल करते समय (जैसे कि GetTicker), संरक्षक द्वारा सामान्य प्रोटोकॉल को भेजा गया अनुरोध प्रारूप भी भिन्न होगा। मुख्य भाग में डेटा (JSON) केवल भिन्न होता हैmethodऔरparams. सामान्य प्रोटोकॉल डिज़ाइन करते समय,methodआप सामग्री के आधार पर विशिष्ट कार्य कर सकते हैं। सभी इंटरफेस के लिए अनुरोध-प्रतिक्रिया परिदृश्य निम्नलिखित हैं।

स्पॉट एक्सचेंज

उदाहरण के लिए, वर्तमान व्यापारिक जोड़ी है:ETH_USDTमैं बाद में विस्तार में नहीं जाऊंगा। वह डेटा जिसे संरक्षक सामान्य प्रोटोकॉल से प्रतिक्रिया की अपेक्षा करता है, मुख्य रूप से डेटा फ़ील्ड में लिखा जाता है, और एक्सचेंज इंटरफ़ेस के मूल डेटा को रिकॉर्ड करने के लिए एक कच्चा फ़ील्ड भी जोड़ा जा सकता है।

  • GetTicker

    • विधि फ़ील्ड: “टिकर”
    • पैरामीटर फ़ील्ड:
    {"symbol":"ETH_USDT"}
    
    • सामान्य प्रोटोकॉल प्रतिक्रिया में होस्ट द्वारा अपेक्षित डेटा:
    {
        "data": {
            "symbol": "ETH_USDT",      // 对应GetTicker函数返回的Ticker结构中的Symbol字段
            "buy": "2922.18",          // ...对应Buy字段
            "sell": "2922.19", 
            "high": "2955", 
            "low": "2775.15", 
            "open": "2787.72", 
            "last": "2922.18", 
            "vol": "249400.888156", 
            "time": "1731028903911"
        },
        "raw": {}                      // 可以增加一个raw字段记录交易所API接口应答的原始数据
    }
    
  • GetDepth

    • विधि फ़ील्ड: “गहराई”
    • पैरामीटर फ़ील्ड:
    {"limit":"30","symbol":"ETH_USDT"}
    
    • सामान्य प्रोटोकॉल प्रतिक्रिया में होस्ट द्वारा अपेक्षित डेटा:
    {
        "data" : {
            "time" : 1500793319499,
            "asks" : [
                [1000, 0.5], [1001, 0.23], [1004, 2.1]
                // ... 
            ],
            "bids" : [
                [999, 0.25], [998, 0.8], [995, 1.4]
                // ... 
            ]
        }
    }
    
  • GetTrades

    • विधि फ़ील्ड: “ट्रेड्स”
    • पैरामीटर फ़ील्ड:
    {"symbol":"eth_usdt"}
    
    • सामान्य प्रोटोकॉल प्रतिक्रिया में होस्ट द्वारा अपेक्षित डेटा:
    { 
        "data": [
            {
                "id": 12232153,
                "time" : 1529919412968,
                "price": 1000,
                "amount": 0.5,
                "type": "buy",             // "buy"、"sell"、"bid"、"ask"
            }, {
                "id": 12545664,
                "time" : 1529919412900,
                "price": 1001,
                "amount": 1,
                "type": "sell",
            }
            // ...
        ]
    }
    
  • GetRecords

    • विधि फ़ील्ड: “रिकॉर्ड्स”
    • पैरामीटर फ़ील्ड:
    {
        "limit":"500",
        "period":"60",          // 60分钟
        "symbol":"ETH_USDT"
    }
    
    • सामान्य प्रोटोकॉल प्रतिक्रिया में होस्ट द्वारा अपेक्षित डेटा:
    {
        "data": [
                // "Time":1500793319000,"Open":1.1,"High":2.2,"Low":3.3,"Close":4.4,"Volume":5.5
                [1500793319, 1.1, 2.2, 3.3, 4.4, 5.5],
                [1500793259, 1.01, 2.02, 3.03, 4.04, 5.05],
                // ...
        ]
    }
    
  • GetMarkets लागु होना

    • विधि फ़ील्ड: “”
    • पैरामीटर फ़ील्ड:
    {}
    
    • सामान्य प्रोटोकॉल प्रतिक्रिया में होस्ट द्वारा अपेक्षित डेटा:
    {}
    
  • GetTickers लागु होना

    • विधि फ़ील्ड: “”
    • पैरामीटर फ़ील्ड:
    {}
    
    • सामान्य प्रोटोकॉल प्रतिक्रिया में होस्ट द्वारा अपेक्षित डेटा:
    {}
    
  • GetAccount

    • विधि फ़ील्ड: “खाते”
    • पैरामीटर फ़ील्ड:
    {}
    
    • सामान्य प्रोटोकॉल प्रतिक्रिया में होस्ट द्वारा अपेक्षित डेटा:
    {
        "data": [
            {"currency": "TUSD", "free": "3000", "frozen": "0"}, 
            {"currency": "BTC", "free": "0.2482982056277609", "frozen": "0"}, 
            // ...
        ]
    }
    
  • GetAssets

    • विधि फ़ील्ड: “संपत्तियाँ”
    • पैरामीटर फ़ील्ड:
    {}
    
    • सामान्य प्रोटोकॉल प्रतिक्रिया में होस्ट द्वारा अपेक्षित डेटा:
    {
        "data": [
            {"currency": "TUSD", "free": "3000", "frozen": "0"},
            {"currency": "BTC", "free": "0.2482982056277609", "frozen": "0"}, 
            // ...
        ]
    }
    
  • CreateOrder / Buy / Sell

    • विधि फ़ील्ड: “व्यापार”
    • पैरामीटर फ़ील्ड:
    {"amount":"0.1","price":"1000","symbol":"BTC_USDT","type":"buy"}
    
    • सामान्य प्रोटोकॉल प्रतिक्रिया में होस्ट द्वारा अपेक्षित डेटा:
    {
        "data": {
            "id": "BTC-USDT,123456"
        }
    }
    
  • GetOrders

    • विधि फ़ील्ड: “ऑर्डर”
    • पैरामीटर फ़ील्ड:
    {"symbol":"ETH_USDT"}
    
    • सामान्य प्रोटोकॉल प्रतिक्रिया में होस्ट द्वारा अपेक्षित डेटा:
    {
        "data": [
            {
                "id": "ETH-USDT,123456",
                "symbol": "ETH_USDT",
                "amount": 0.25,
                "price": 1005,
                "deal_amount": 0,
                "avg_price": "1000",
                "type": "buy",         // "buy"、"sell"
                "status": "pending",   // "pending", "pre-submitted", "submitting", "submitted", "partial-filled"
            }, 
            // ...
        ]
    }
    
  • GetOrder

    • विधि फ़ील्ड: “ऑर्डर”
    • पैरामीटर फ़ील्ड:
    {
        "id":"ETH-USDT,123456",       // 策略中调用:exchange.GetOrder("ETH-USDT,123456")
        "symbol":"ETH_USDT"
    }
    
    • सामान्य प्रोटोकॉल प्रतिक्रिया में होस्ट द्वारा अपेक्षित डेटा:
    { 
        "data": {
            "id": "ETH-USDT,123456",
            "symbol": "ETH_USDT"
            "amount": 0.15,
            "price": 1002,
            "status": "pending",    // "pending", "pre-submitted", "submitting", "submitted", "partial-filled", "filled", "closed", "finished", "partial-canceled", "canceled"
            "deal_amount": 0,
            "type": "buy",          // "buy"、"sell"
            "avg_price": 0,         // 如果交易所没有提供,在处理时可以赋值为0
        }
    }
    
  • GetHistoryOrders

    • विधि फ़ील्ड: “historyorders”
    • पैरामीटर फ़ील्ड:
    {"limit":0,"since":0,"symbol":"ETH_USDT"}
    
    • सामान्य प्रोटोकॉल प्रतिक्रिया में होस्ट द्वारा अपेक्षित डेटा:
    {
        "data": [
            {
                "id": "ETH-USDT,123456",
                "symbol": "ETH_USDT",
                "amount": 0.25,
                "price": 1005,
                "deal_amount": 0,
                "avg_price": 1000,
                "type": "buy",       // "buy"、"sell"
                "status": "filled",  // "filled"
            }, 
            // ...
        ]
    }
    
  • CancelOrder

    • विधि फ़ील्ड: “रद्द करें”
    • पैरामीटर फ़ील्ड:
    {"id":"ETH-USDT,123456","symbol":"ETH_USDT"}
    
    • सामान्य प्रोटोकॉल प्रतिक्रिया में होस्ट द्वारा अपेक्षित डेटा:
    {
        "data": true    // 只要该JSON中没有error字段,都默认为撤单成功
    }
    
  • IO

एक्सचेंज.IO फ़ंक्शन का उपयोग एक्सचेंज इंटरफ़ेस तक सीधे पहुंचने के लिए किया जाता है। उदाहरण के लिए, हम इसका उपयोग करते हैंGET /api/v5/trade/orders-pending, 参数:instType=SPOT,instId=ETH-USDTउदाहरण के लिए।

  // 策略实例中调用
  exchange.IO("api", "GET", "/api/v5/trade/orders-pending", "instType=SPOT&instId=ETH-USDT")
  • विधि क्षेत्र:"__api_/api/v5/trade/orders-pending"विधि फ़ील्ड _api से शुरू होती है, जो यह दर्शाता है कि यह रणनीति इंस्टैंस में exchange.IO फ़ंक्शन कॉल द्वारा ट्रिगर किया गया है।

  • पैरामीटर फ़ील्ड:

    {"instId":"ETH-USDT","instType":"SPOT"}   // instType=SPOT&instId=ETH-USDT编码的参数会被还原为JSON
    
  • सामान्य प्रोटोकॉल प्रतिक्रिया में होस्ट द्वारा अपेक्षित डेटा:

    {
        "data": {"code": "0", "data": [], "msg": ""}    // data属性值为交易所API:GET /api/v5/trade/orders-pending 应答的数据
    }
    
  • अन्य रणनीति उदाहरणों में उपयोग किए गए अन्य इन्वेंटर प्लेटफ़ॉर्म API फ़ंक्शन, जैसे: exchange.Go()exchange.GetRawJSON()इस तरह के कार्यों को एनकैप्सुलेट करने की आवश्यकता नहीं होती है, तथा कॉलिंग विधि और कार्यक्षमता अपरिवर्तित रहती है।

वायदा एक्सचेंज

स्पॉट एक्सचेंजों के सभी कार्यों का समर्थन करने के अलावा, वायदा एक्सचेंजों में कुछ API फ़ंक्शन भी होते हैं जो वायदा एक्सचेंजों के लिए अद्वितीय होते हैं।

लागु होना

  • GetPositions
  • SetMarginLevel
  • GetFundings

सामान्य प्रोटोकॉल उदाहरण का पायथन संस्करण

REST सामान्य प्रोटोकॉल - OKX एक्सचेंज REST API इंटरफ़ेस तक पहुंच और इसे स्पॉट एक्सचेंज ऑब्जेक्ट के रूप में समाहित करना। अनुरोध और प्रतिक्रिया डेटा एनकैप्सुलेशन के लिए एक सामान्य इंटरफ़ेस कार्यान्वित किया गया। निजी इंटरफ़ेस हस्ताक्षर, अनुरोध और प्रतिक्रिया डेटा एनकैप्सुलेशन को कार्यान्वित किया गया। यह उदाहरण मुख्य रूप से परीक्षण और सीखने के लिए है। अन्य इंटरफेस परीक्षण के लिए होस्ट को सीधे जवाब देने के लिए सिम्युलेटेड डेटा का उपयोग करते हैं।

”`python import http.server import socketserver import json import urllib.request import urllib.error import argparse import ssl import hmac import hashlib import base64

from datetime import datetime

ssl._create_default_https_context = ssl._create_unverified_context

class BaseProtocol: ERR_NOT_SUPPORT = {“error”: “not support”}

def __init__(self, apiBase, accessKey, secretKey):
    self._apiBase = apiBase
    self._accessKey = accessKey
    self._secretKey = secretKey


def _httpRequest(self, method, path, query="", params={}, addHeaders={}):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6', 
        'Content-Type': 'application/json; charset=UTF-8'
    }

    # add headers
    for key in addHeaders:
        headers[key] = addHeaders[key]

    if method == "GET":
        url = f"{self._apiBase}{path}?{query}" if query != "" else f"{self._apiBase}{path}"
        req = urllib.request.Request(url, method=method, headers=headers)
    else:
        url = f"{self._apiBase}{path}"
        req = urllib.request.Request(url, json.dumps(params, separators=(',', ':')).encode('utf-8'), method=method, headers=headers)

    print(f'send request by protocol: {self.exName}, req:', req.method, req.full_url, req.headers, req.data, "\n")

    try:
        with urllib.request.urlopen(req) as resp:
            data = json.loads(resp.read())
    except json.JSONDecodeError:
        data = {"error": "Invalid JSON response"}
    except urllib.error.HTTPError as e:
        data = {"error": f"HTTP error: {e.code}"}
    except urllib.error.URLError as e:
        data = {"error": f"URL error: {e.reason}"}
    except Exception as e:
        data = {"error": f"Exception occurred: {str(e)}"}

    print(f'protocol response received: {self.exName}, resp:', data, "\n")

    return data


def GetTickers(self):
    return self.ERR_NOT_SUPPORT


def GetMarkets(self):
    return self.ERR_NOT_SUPPORT


def GetTicker(self, symbol):
    return self.ERR_NOT_SUPPORT


def GetDepth(self, symbol=""):
    return self.ERR_NOT_SUPPORT


def GetTrades(self, symbol=""):
    return self.ERR_NOT_SUPPORT


def GetRecords(self, symbol, period, limit):
    return self.ERR_NOT_SUPPORT


def GetAssets(self):
    return self.ERR_NOT_SUPPORT


def GetAccount(self):
    return self.ERR_NOT_SUPPORT


def CreateOrder(self, symbol, side, price, amount):
    return self.ERR_NOT_SUPPORT


def GetOrders(self, symbol=""):
    return self.ERR_NOT_SUPPORT


def GetOrder(self, orderId):
    return self.ERR_NOT_SUPPORT


def CancelOrder(self, orderId):
    return self.ERR_NOT_SUPPORT


def GetHistoryOrders(self, symbol, since, limit):
    return self.ERR_NOT_SUPPORT


def GetPostions(self, symbol=""):
    return self.ERR_NOT_SUPPORT


def SetMarginLevel(self, symbol, marginLevel):
    return self.ERR_NOT_SUPPORT


def GetFundings(self, symbol=""):
    return self.ERR_NOT_SUPPORT


def IO(self, params):
    return self.ERR_NOT_SUPPORT

class ProtocolFactory: @staticmethod def createExWrapper(apiBase, accessKey, secretKey, exName) -> BaseProtocol: if exName == “OKX”: return CustomProtocolOKX(apiBase, accessKey, secretKey, exName) else: raise ValueError(f’Unknown exName: {exName}‘)

class CustomProtocolOKX(BaseProtocol): “”” CustomProtocolOKX - OKX API Wrapper

# TODO: add information.
"""

def __init__(self, apiBase, accessKey, secretKey, exName):
    secretKeyList = secretKey.split(",")
    self.exName = exName
    self._x_simulated_trading = 0
    if len(secretKeyList) > 1:
        self._passphrase = secretKeyList[1]
        if len(secretKeyList) > 2:
            if secretKeyList[2] == "simulate":
                self._x_simulated_trading = 1
    else:
        raise ValueError(f"{self.exName}: invalid secretKey format.")
    super().__init__(apiBase, accessKey, secretKeyList[0])


def getCurrencys(self, symbol):
    baseCurrency, quoteCurrency = "", ""
    arrCurrency = symbol.split("_")
    if len(arrCurrency) == 2:
        baseCurrency = arrCurrency[0]
        quoteCurrency = arrCurrency[1]
    return baseCurrency, quoteCurrency


def getSymbol(self, instrument):
    arrCurrency = instrument.split("-")
    if len(arrCurrency) == 2:
        baseCurrency = arrCurrency[0]
        quoteCurrency = arrCurrency[1]
    else:
        raise ValueError(f"{self.exName}: invalid instrument: {instrument}")
    return f'{baseCurrency}_{quoteCurrency}'


def callUnsignedAPI(self, httpMethod, path, query="", params={}):
    return self._httpRequest(httpMethod, path, query, params)


def callSignedAPI(self, httpMethod, path, query="", params={}):
    strTime = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
    if httpMethod == "GET":
        jsonStr = json.dumps(params, separators=(',', ':')) if len(params) > 0 else ""
    else:
        jsonStr = json.dumps(params, separators=(',', ':')) if len(params) > 0 else "{}"
    message = f'{strTime}{httpMethod}{path}{jsonStr}'
    if httpMethod == "GET" and query != "":
        message = f'{strTime}{httpMethod}{path}?{query}{jsonStr}'
    mac = hmac.new(bytes(self._secretKey, encoding='utf8'), bytes(message, encoding='utf-8'), digestmod='sha256')
    signature = base64.b64encode(mac.digest())

    headers = {}
    if self._x_simulated_trading == 1:
        headers["x-simulated-trading"] = str(self._x_simulated_trading)
    headers["OK-ACCESS-KEY"] = self._accessKey
    headers["OK-ACCESS-PASSPHRASE"] = self._passphrase
    headers["OK-ACCESS-TIMESTAMP"] = strTime        
    headers["OK-ACCESS-SIGN"] = signature
    return self._httpRequest(httpMethod, path, query, params, headers)


# Encapsulates requests to the exchange API.
def GetTicker(self, symbol):
    """
    GET /api/v5/market/ticker , param: instId 
    """

    baseCurrency, quoteCurrency = self.getCurrencys(symbol)
    if baseCurrency == "" or quoteCurrency == "":
        return {"error": "invalid symbol"}

    path = "/api/v5/market/ticker"
    query = f'instId={baseCurrency}-{quoteCurrency}'
    data = self.callUnsignedAPI("GET", path, query=query)
    if "error" in data.keys() and "data" not in data.keys():
        return data

    ret_data = {}
    if data["code"] != "0" or not isinstance(data["data"], list):
        return {"error": json.dumps(data, ensure_ascii=False)}
    for tick in data["data"]:
        if not all(k in tick for k in ("instId", "bidPx", "askPx", "high24h", "low24h", "vol24h", "ts")):
            return {"error": json.dumps(data, ensure_ascii=False)}

        ret_data["symbol"] = self.getSymbol(tick["instId"])
        ret_data["buy"] = tick["bidPx"]
        ret_data["sell"] = tick["askPx"]
        ret_data["high"] = tick["high24h"]
        ret_data["low"] = tick["low24h"]
        ret_data["open"] = tick["open24h"]
        ret_data["last"] = tick["last"]
        ret_data["vol"] = tick["vol24h"]
        ret_data["time"] = tick["ts"]

    return {"data": ret_data, "raw": data}


def GetDepth(self, symbol):
    """
    TODO: Implementation code
    """

    # Mock data for testing.
    ret_data = {            
        "time" : 1500793319499,
        "asks" : [
            [1000, 0.5], [1001, 0.23], [1004, 2.1]
        ],
        "bids" : [
            [999, 0.25], [998, 0.8], [995, 1.4]
        ]            
    }

    return {"data": ret_data}


def GetTrades(self, symbol):
    """
    TODO: Implementation code
    """

    # Mock data for testing.
    ret_data = [
        {
            "id": 12232153,
            "time" : 1529919412968,
            "price": 1000,
            "amount": 0.5,
            "type": "buy",
        }, {
            "id": 12545664,
            "time" : 1529919412900,
            "price": 1001,
            "amount": 1,
            "type": "sell",
        }
    ]

    return {"data": ret_data}


def GetRecords(self, symbol, period, limit):
    """
    TODO: Implementation code
    """

    # Mock data for testing.
    ret_data = [
        [1500793319, 1.1, 2.2, 3.3, 4.4, 5.5],
        [1500793259, 1.01, 2.02, 3.03, 4.04, 5.05],
    ]

    return {"data": ret_data}


def GetMarkets(self):
    """
    TODO: Implementation code
    """

    ret_data = {}

    return {"data": ret_data}


def GetTickers(self):
    """
    TODO: Implementation code
    """

    ret_data = {}

    return {"data": ret_data}


def GetAccount(self):
    """
    GET /api/v5/account/balance
    """

    path = "/api/v5/account/balance"
    data = self.callSignedAPI("GET", path)

    ret_data = []
    if data["code"] != "0" or "data" not in data or not isinstance(data["data"], list):
        return {"error": json.dumps(data, ensure_ascii=False)}
    for ele in data["data"]:
        if "details" not in ele or not isinstance(ele["details"], list):
            return {"error": json.dumps(data, ensure_ascii=False)}
        for detail in ele["details"]:
            asset = {"currency": detail["ccy"], "free": detail["availEq"], "frozen": detail["ordFrozen"]}
            if detail["availEq"] == "":
                asset["free"] = detail["availBal"]
            ret_data.append(asset)
    return {"data": ret_data, "raw": data}


def GetAssets(self):
    """
    TODO: Implementation code
    """

    # Mock data for testing.
    ret_data = [
        {"currency": "TUSD", "free": "3000", "frozen": "0"},
        {"currency": "BTC", "free": "0.2482982056277609", "frozen": "0"}
    ]

    return {"data": ret_data}


def CreateOrder(self, symbol, side, price, amount):
    """
    TODO: Implementation code
    """

    # Mock data for testing.
    ret_data = {
        "id": "BTC-USDT,123456"
    }

    return {"data": ret_data}


def GetOrders(self, symbol):
    """
    GET /api/v5/trade/orders-pending  instType SPOT instId  after limit
    """

    baseCurrency, quoteCurrency = self.getCurrencys(symbol)
    if baseCurrency == "" or quoteCurrency == "":
        return {"error": "invalid symbol"}

    path = "/api/v5/trade/orders-pending"
    after = ""
    limit = 100

    ret_data = []
    while True:
        query = f"instType=SPOT&instId={baseCurrency}-{quoteCurrency}&limit={limit}"
        if after != "":
            query = f"instType=SPOT&instId={baseCurrency}-{quoteCurrency}&limit={limit}&after={after}"

        data = self.callSignedAPI("GET", path, query=query)

        if data["code"] != "0" or not isinstance(data["data"], list):
            return {"error": json.dumps(data, ensure_ascii=False)}
        for ele in data["data"]:
            order = {}

            order["id"] = f'{ele["instId"]},{ele["ordId"]}'
            order["symbol"] = f'{baseCurrency}-{quoteCurrency}'
            order["amount"] = ele["sz"]
            order["price"] = ele["px"]
            order["deal_amount"] = ele["accFillSz"]
            order["avg_price"] = 0 if ele["avgPx"] == "" else ele["avgPx"]
            order["type"] = "buy" if ele["side"] == "buy" else "sell"
            order["state"] = "pending"

            ret_data.append(order)
            after = ele["ordId"]

        if len(data["data"]) < limit:
            break

    return {"data": ret_data}


def GetOrder(self, orderId):
    """
    TODO: Implementation code
    """

    # Mock data for testing.
    ret_data = {
        "id": "ETH-USDT,123456",
        "symbol": "ETH_USDT",
        "amount": 0.15,
        "price": 1002,
        "status": "pending",
        "deal_amount": 0,
        "type": "buy",
        "avg_price": 0,
    }

    return {"data": ret_data}


def GetHistoryOrders(self, symbol, since, limit):
    """
    TODO: Implementation code
    """

    # Mock data for testing.
    ret_data = [
        {
            "id": "ETH-USDT,123456",
            "symbol": "ETH_USDT",
            "amount": 0.25,
            "price": 1005,
            "deal_amount": 0,
            "avg_price": 1000,
            "type": "buy",
            "status": "filled"
        }
    ]

    return {"data": ret_data}


def CancelOrder(self, orderId):
    """
    TODO: Implementation code
    """

    # Mock data for testing.
    ret_data = True

    return {"data": ret_data}


def IO(self, httpMethod, path, params={}):
    if httpMethod == "GET":
        query = urllib.parse.urlencode(params)
        data = self.callSignedAPI(httpMethod, path, query=query)
    else:
        data = self.callSignedAPI(httpMethod, path, params=params)

    if data["code"] != "0":
        return {"error": json.dumps(data, ensure_ascii=False)}

    return {"data": data}

class HttpServer(http.server.SimpleHTTPRequestHandler): def init(self, *args, **kwargs): self.request_body = None self.request_path = None super().init(*args, **kwargs)

def log_message(self, format, *args):
    return 


def _sendResponse(self, body):
    self.send_response(200)
    self.send_header('Content-type', 'application/json; charset=utf-8')
    self.end_headers()
    self.wfile.write(json.dumps(body).encode('utf-8'))


def do_GET(self):
    # The FMZ.COM custom protocol only send GET method request
    self._sendResponse({"error": "not support GET method."})


def do_POST(self):
    """
    Returns:
        json: success, {"data": ...}
        json: error,   {"error": ...}
    """

    contentLen = int(self.headers['Content-Length'])
    self.request_body = self.rfile.read(contentLen)
    self.request_path = self.path
    exName = self.request_path.lstrip("/")

    # Print the request received from the FMZ.COM robot
    print(f"--------- request received from the FMZ.COM robot: --------- \n {self.requestline} | Body: {self.request_body} | Headers: {self.headers} \n")

    try:
        data = json.loads(self.request_body)
    except json.JSONDecodeError:
        data = {"error": self.request_body.decode('utf-8')}
        self._sendResponse(data)
        return 

    # fault tolerant
    if not all(k in data for k in ("access_key", "secret_key", "method", "params")):
        data = {"error": "missing required parameters"}
        self._sendResponse(data)
        return

    respData = {}
    accessKey = data["access_key"]
    secretKey = data["secret_key"]
    method = data["method"]
    params = data["params"]
    exchange = ProtocolFactory.createExWrapper("https://www.okx.com", accessKey, secretKey, exName)

    if method == "ticker":
        symbol = str(params["symbol"]).upper()
        respData = exchange.GetTicker(symbol)
    elif method == "depth":
        symbol = str(params["symbol"]).upper()
        respData = exchange.GetDepth(symbol)
    elif method == "trades":
        symbol = str(params["symbol"]).upper()
        respData = exchange.GetTrades(symbol)
    elif method == "records":
        symbol = str(params["symbol"]).upper()
        period = int(params["perio