संसाधन लोड हो रहा है... लोड करना...

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

लेखक:आविष्कारक मात्रा - छोटे सपने, बनाया गयाः 2024-10-29 14:37:56, अद्यतनः 2024-11-12 21:58:55

[TOC]

img

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

इस लेख मेंRESTप्रोटोकॉल एक्सेस के उदाहरण के रूप में, यह समझाया गया है कि कैसे आविष्कारक के क्वांटिफाइड ट्रेडिंग प्लेटफॉर्म के सामान्य प्रोटोकॉल का उपयोग करके ओकेएक्स एक्सचेंज के एपीआई को संलग्न और एक्सेस किया जाता है।

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

1। विनिमय को कॉन्फ़िगर करें

आविष्कारक क्वांटिफाइड एक्सचेंज प्लेटफॉर्म विनिमय के लिए पृष्ठ को कॉन्फ़िगर करता हैः

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

img

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

लेख में प्रकाशित OKX प्लगइन कॉन्फ़िगरेशन का स्क्रीनशॉट नीचे दिया गया हैः

img

ओकेएक्स एक्सचेंज के लिए गुप्त कुंजी विन्यास जानकारीः

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

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

  • 1। प्रबंधक आविष्कारक के क्वांटिफाइड ट्रेडिंग प्लेटफॉर्म पर चलाने के लिए किसी भी रणनीतिक वास्तविक डिस्क पर एक ट्रस्ट को तैनात करना आवश्यक है, एक विशिष्ट तैनाती ट्रस्ट प्लेटफॉर्म ट्यूटोरियल को संदर्भित कर सकता है, जो यहां अधिक नहीं है।

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

3, नीति उदाहरण FMZ के लिए एपीआई फ़ंक्शन का अनुरोध करता है

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

डिबगिंग टूल पेजः

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: मंच "एक्सचेंज कॉन्फ़िगरेशन" के दौरान ऊपर दिए गए एक्सचेंज की गुप्त कुंजी
  • method: नीति में इंटरफेस को कॉल करने से संबंधित है, कॉलexchange.GetTicker()यह एक बहुत ही अच्छा समय है।methodयानीticker
  • nonce: अनुरोध के समय की अवधि।
  • params: नीति में इंटरफेस कॉल होने पर संबंधित पैरामीटर, इस मामले मेंexchange.GetTicker()जब कॉल किया जाता है, तो संबंधित पैरामीटर हैंः{"symbol":"LTC_USDT"}

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

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

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

आम तौर पर एक्सचेंज इंटरफेस में गेट / पोस्ट / पुट / डिलीट जैसे तरीके होते हैं, जिन्हें सार्वजनिक और निजी इंटरफेस में विभाजित किया जाता है।

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

सामान्य प्रोटोकॉल प्रक्रिया को एक्सचेंज इंटरफेस प्रतिक्रिया डेटा प्राप्त होता है, जिसे आगे संसाधित किया जाता है, जो कि संरक्षक द्वारा अपेक्षित डेटा का गठन करता है। ओकेएक्स स्टॉक एक्सचेंज के संदर्भ में, पाइथन सामान्य प्रोटोकॉल उदाहरण में कस्टमप्रोटोकॉल ओकेएक्स वर्ग कार्यान्वयन मेंGetTickerGetAccountसम है।

5। सामान्य प्रोटोकॉल प्रोग्राम डेटा को ट्रस्ट को जवाब देता है

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

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

  • एक्सचेंज इंटरफेस को कॉल करने के लिए सामान्य प्रोटोकॉल प्रक्रिया सफल रहीः

    {
        "data": null,  // "data" can be of any type 
        "raw": null    // "raw" can be of any type 
    }
    
    • data: उस फ़ील्ड का विशिष्ट संरचना और अनुरोधों में से एक जो सामान्य प्रोटोकॉल प्रक्रिया द्वारा प्राप्त किया जाता हैmethodसंबंधित, एफएमजेड प्लेटफॉर्म एपीआई फ़ंक्शन के निर्माण के लिए उपयोग किए जाने वाले डेटा संरचनाओं को अंततः वापस करने के लिए, सभी इंटरफेस नीचे सूचीबद्ध हैं।
    • raw: यह फ़ील्ड एक्सचेंज एपीआई इंटरफेस प्रतिक्रियाओं के लिए कच्चे डेटा को पारित कर सकता है, जैसे किexchange.GetTicker()एक फ़ंक्शन लौटता है कि टिकर संरचना, टिकर संरचना की जानकारी फ़ील्ड में दर्ज किया गया हैrawफ़ील्ड औरdataफ़ील्ड का डेटा; प्लेटफ़ॉर्म के एपीआई फ़ंक्शन, कुछ को इस डेटा की आवश्यकता नहीं है।
  • एक्सचेंज इंटरफेस पर कॉल करने के लिए सामान्य प्रोटोकॉल प्रोग्राम विफल (व्यापार त्रुटि, नेटवर्क त्रुटि आदि)

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

एक रणनीति कार्यक्रम द्वारा प्राप्त सामान्य प्रोटोकॉल प्रतिक्रिया डेटा का प्रदर्शन करेंः

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

img

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

उपरोक्त एक सामान्य प्रोटोकॉल प्रोग्राम है जो एक्सेस (FMZ unwrapped) एक्सचेंज एपीआई में भाग लेने के लिए एक संक्षिप्त प्रक्रिया है, जो केवल FMZ प्लेटफॉर्म डिबगिंग टूल में कॉल के बारे में बताता है।exchange.GetTicker()फ़ंक्शन के समय की प्रक्रिया. सभी प्लेटफ़ॉर्म एपीआई फ़ंक्शन के बीच बातचीत के विवरण का विस्तार नीचे दिया गया है.

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

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

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

नकदी एक्सचेंज

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

  • GetTicker

    • method फ़ील्डः कंक्रीट चिपकने वाला
    • params फ़ील्डः
      {"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接口应答的原始数据
      }
      
  • गहराई प्राप्त करें

    • method फ़ील्डःdepth
    • params फ़ील्डः
      {"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

    • method फ़ील्डः ट्रेडों को जोड़ना
    • params फ़ील्डः
      {"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

    • method फ़ील्डः records
    • params फ़ील्डः
      {
          "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पूरा होना

    • method फ़ील्ड:""
    • params फ़ील्डः
      {}
      
    • एक सामान्य प्रोटोकॉल के जवाब में डेटा की उम्मीद करने वाले ट्रस्टः
      {}
      
  • GetTickersपूरा होना

    • method फ़ील्ड:""
    • params फ़ील्डः
      {}
      
    • एक सामान्य प्रोटोकॉल के जवाब में डेटा की उम्मीद करने वाले ट्रस्टः
      {}
      
  • खाता प्राप्त करें

    • method फ़ील्डः accounts
    • params फ़ील्डः
      {}
      
    • एक सामान्य प्रोटोकॉल के जवाब में डेटा की उम्मीद करने वाले ट्रस्टः
      {
          "data": [
              {"currency": "TUSD", "free": "3000", "frozen": "0"}, 
              {"currency": "BTC", "free": "0.2482982056277609", "frozen": "0"}, 
              // ...
          ]
      }
      
  • GetAssets

    • method फ़ील्डः एसेट एसेट
    • params फ़ील्डः
      {}
      
    • एक सामान्य प्रोटोकॉल के जवाब में डेटा की उम्मीद करने वाले ट्रस्टः
      {
          "data": [
              {"currency": "TUSD", "free": "3000", "frozen": "0"},
              {"currency": "BTC", "free": "0.2482982056277609", "frozen": "0"}, 
              // ...
          ]
      }
      
  • क्रिएटऑर्डर / खरीदें / बेचें

    • method फ़ील्डः ट्रेड करें ट्रेड करें
    • params फ़ील्डः
      {"amount":"0.1","price":"1000","symbol":"BTC_USDT","type":"buy"}
      
    • एक सामान्य प्रोटोकॉल के जवाब में डेटा की उम्मीद करने वाले ट्रस्टः
      {
          "data": {
              "id": "BTC-USDT,123456"
          }
      }
      
  • GetOrders प्राप्त करें

    • method फ़ील्डः orders
    • params फ़ील्डः
      {"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"
              }, 
              // ...
          ]
      }
      
  • प्राप्त करेंआदेश

    • method फ़ील्डः order तालिका तालिका
    • params फ़ील्डः
      {
          "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 प्राप्त करें

    • method फ़ील्डः हिस्ट्री ऑर्डर
    • params फ़ील्डः
      {"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"
              }, 
              // ...
          ]
      }
      
  • आदेश रद्द करें

    • method फ़ील्डः cancel
    • params फ़ील्डः
      {"id":"ETH-USDT,123456","symbol":"ETH_USDT"}
      
    • एक सामान्य प्रोटोकॉल के जवाब में डेटा की उम्मीद करने वाले ट्रस्टः
      {
          "data": true    // 只要该JSON中没有error字段,都默认为撤单成功
      }
      
  • आईओ

    exchange.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")
    
    • method फ़ील्डः"__api_/api/v5/trade/orders-pending"विधि फ़ील्ड की सामग्री __api_ से शुरू होती है, जो बताती है कि यह नीति उदाहरण में exchange.IO फ़ंक्शन कॉल द्वारा ट्रिगर की गई है।
    • params फ़ील्डः
      {"instId":"ETH-USDT","instType":"SPOT"}   // instType=SPOT&instId=ETH-USDT编码的参数会被还原为JSON
      
    • एक सामान्य प्रोटोकॉल के जवाब में डेटा की उम्मीद करने वाले ट्रस्टः
      {
          "data": {"code": "0", "data": [], "msg": ""}    // data属性值为交易所API:GET /api/v5/trade/orders-pending 应答的数据
      }
      
  • अन्य रणनीति उदाहरण में उपयोग किए जाने वाले अन्य आविष्कारक प्लेटफ़ॉर्म एपीआई फ़ंक्शन, जैसेःexchange.Go()exchange.GetRawJSON()उदाहरण के लिए, फ़ंक्शन को पैक करने की आवश्यकता नहीं है, कॉल करने का तरीका, कार्यशीलता अपरिवर्तित है।

फ्यूचर्स एक्सचेंज

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

पूरा होना

  • GetPositions
  • सीमा स्तर सेट करें
  • प्राप्त करें

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

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

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["period"])
            limit = int(params["limit"])
            respData = exchange.GetRecords(symbol, period, limit)
        elif method == "accounts":
            respData = exchange.GetAccount()
        elif method == "assets":
            respData = exchange.GetAssets()
        elif method == "trade":
            amount = float(params["amount"])
            price = float(params["price"])
            symbol = str(params["symbol"])
            tradeType = str(params["type"])
            respData = exchange.CreateOrder(symbol, tradeType, price, amount)
        elif method == "orders":
            symbol = str(params["symbol"]).upper()
            respData = exchange.GetOrders(symbol)
        elif method == "order":
            orderId = str(params["id"])
            respData = exchange.GetOrder(orderId)
        elif method == "historyorders":
            symbol = str(params["symbol"])
            since = int(params["since"])
            limit = int(params["limit"])
            respData = exchange.GetHistoryOrders(symbol, since, limit)
        elif method == "cancel":
            orderId = str(params["id"])
            respData = exchange.CancelOrder(orderId)
        elif method[:6] == "__api_":
            respData = exchange.IO(self.headers["Http-Method"], method[6:], params)
        else:
            respData = {"error": f'invalid method: {method}'}

        # Print the response to send to FMZ.COM robot
        print(f"response to send to FMZ.COM robot: {respData} \n")

        self._sendResponse(respData)


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Run a FMZ.COM custom protocol plugin.")
    parser.add_argument("--port", type=int, default=6666, help="Port to run the server on.")
    parser.add_argument("--address", type=str, default="localhost", help="Address to bind the server to.")
    args = parser.parse_args() 

    with socketserver.TCPServer((args.address, args.port), HttpServer) as httpd:
        print(f"running... {args.address}:{args.port}", "\n")
        httpd.serve_forever()

अधिक