وسائل لوڈ ہو رہے ہیں... لوڈنگ...

ایجاد کنندہ کوالٹی ٹرانزیکشن پلیٹ فارم کے لئے جنرل پروٹوکول تک رسائی کی رہنمائی

مصنف:ایجاد کاروں کی مقدار - خواب, تخلیق: 2024-10-29 14:37:56, تازہ کاری: 2024-11-12 21:58:55

[TOC]

img

موجد کی کوٹیفیکیشن ٹریڈنگ پلیٹ فارم بہت سے کریپٹوکرنسی تبادلے کی حمایت کرتا ہے اور مارکیٹ میں موجود اہم تبادلے کا احاطہ کرتا ہے۔ تاہم ، ابھی بھی بہت سارے تبادلے موجود ہیں جن کو احاطہ نہیں کیا گیا ہے ، اور جن صارفین کو ان تبادلے کو استعمال کرنے کی ضرورت ہے ان کے لئے موجد کی کوٹیفیکیشن جنرل پروٹوکول کے ذریعہ رسائی حاصل کی جاسکتی ہے۔RESTمعاہدہ یافکسڈاس معاہدے کے پلیٹ فارم تک بھی رسائی حاصل ہے۔

اس مضمون میںRESTپروٹوکول تک رسائی کی مثال کے طور پر ، وضاحت کی گئی ہے کہ کس طرح ایجاد کنندہ کوالٹی ٹریڈنگ پلیٹ فارم کے جنرل پروٹوکول کا استعمال کرتے ہوئے او کے ایکس ایکس ایکسچینج کو پیکیج کرنے اور ان تک رسائی حاصل کرنے کے لئے اے پی آئی کا استعمال کیا جاسکتا ہے۔ اگر کوئی خاص وضاحت نہیں ہے تو ، اس مضمون میں REST جنرل پروٹوکول کا حوالہ دیا گیا ہے۔

  • جنرل پروٹوکول کے کام کا عمل یہ ہے: درخواست کا عمل: پالیسی کی مثالیں جو منتظمین پر چلتی ہیں -> عمومی پروٹوکول پروسیسنگ -> ایکسچینج API جواب دینے کا عمل: ایکسچینج API -> جنرل پروٹوکول پروسیسنگ -> پالیسی کی مثالیں جو منتظمین پر چلتی ہیں

1، تبادلہ کی ترتیب

ان کے خیال میں اس طرح کے ایکسپورٹ کے بارے میں بہت کچھ ہے۔

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

img

  • پروٹوکول کا انتخاب: "عام پروٹوکول" کا انتخاب کریں۔
  • سروس ایڈریس: جنرل پروٹوکول پروگرام بنیادی طور پر ایک آر پی سی سروس ہے اس کے علاوہ، یہ ضروری ہے کہ آپ کو اس بات کا یقین کرنے کی ضرورت ہے کہ آپ کو ایکسپورٹ کی تشکیل کے دوران سروس ایڈریس، پورٹ، اور اسی طرح کی وضاحت کی جائے گی.托管者上运行的策略实例 -> 通用协议程序اس عمل کے دوران ، منتظمین کو معلوم ہوتا ہے کہ جنرل پروٹوکول پر عملدرآمد کرنے کے لئے کہاں جانا ہے۔ مثال کے طور پرhttp://127.0.0.1:6666/OKXعام طور پر ، عام پروٹوکول کے پروگراموں کو میزبان کے ساتھ ایک ہی آلہ (سرور) پر چلایا جاتا ہے ، لہذا خدمت کا پتہ مقامی میزبان پر لکھا جاتا ہے ، اور پورٹ ایک نظام کا استعمال کرتے ہوئے خالی ہوتا ہے۔
  • رسائی کی چابی:托管者上运行的策略实例 -> 通用协议程序اس عمل کے دوران ، تبادلے کی تشکیل کی معلومات کو منتقل کیا جاتا ہے۔
  • خفیہ کلید:托管者上运行的策略实例 -> 通用协议程序اس عمل کے دوران ، تبادلے کی تشکیل کی معلومات کو منتقل کیا جاتا ہے۔
  • ٹیگز: ایجاد کنندہ کوالٹی ٹریڈنگ پلیٹ فارم پر ایکسچینج آبجیکٹ ٹیگ جو کسی ایکسچینج آبجیکٹ کی نشاندہی کرنے کے لئے استعمال ہوتا ہے۔

اس مضمون میں او کے ایکس پلگ ان کی تشکیل کا اسکرین شاٹ شائع کیا گیا ہے:

img

OKX ایکسچینج کی خفیہ کلید کی ترتیب کی معلومات:

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

2، منتظمین اور پلگ انز کو تعینات کریں

  • 1، منتظمین کسی بھی حکمت عملی کو ایجاد کنندہ کے مقداری تجارت کے پلیٹ فارم پر چلانے کے لئے ایک ٹاسٹر کو تعینات کرنا ضروری ہے ، مخصوص تعیناتی ٹاسٹر پلیٹ فارم ٹیوٹوریل کا حوالہ دے سکتا ہے ، جس کا یہاں مزید ذکر نہیں ہے۔

  • 2، جنرل پروٹوکول (plugin) میزبان اور جنرل پروٹوکول عام طور پر ایک ہی ڈیوائس پر تعینات ہوتے ہیں۔ جنرل پروٹوکول (ایس پی) پروگرام کسی بھی زبان کا استعمال کرتے ہوئے ڈیزائن لکھ سکتے ہیں ، یہ پیتھون 3 کا استعمال کرتے ہوئے لکھا گیا ہے۔ کسی بھی پیتھون پروگرام کو چلانے کی طرح ، براہ راست انجام دیا جاسکتا ہے (پہلے سے پیتھون ماحول کی مختلف ترتیبات) ۔ ایف ایم زیڈ پر پائیٹن پروگراموں کو چلانے کی بھی حمایت کی جاتی ہے ، لیکن یہ بھی ممکن ہے کہ اس پروٹوکول کو ایک حقیقی ڈسک کے طور پر چلائیں تاکہ موجد کو کوانٹیمیٹڈ ٹریڈنگ پلیٹ فارم کو غیر پیکڈ ایکسچینج 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
  • nonce: درخواست کے وقت کی گھڑی۔
  • پیرامیٹرز: پالیسی میں جب انٹرفیس کال ہوتی ہے تو متعلقہ پیرامیٹرز، اس مثال میںexchange.GetTicker()جب کال کی جاتی ہے تو ، متعلقہ پیرامیٹرز یہ ہیں:{"symbol":"LTC_USDT"}

4، جنرل پروٹوکول کے طریقہ کار کو ایکسچینج انٹرفیس تک رسائی

جب یو پی پی پروگرام کو منتظمین کی طرف سے درخواست موصول ہوتی ہے تو ، اس کی درخواست میں موجود معلومات کے مطابق معلوم کیا جاسکتا ہے: حکمت عملی کی درخواست کرنے والے پلیٹ فارم API فنکشن ((بشمول پیرامیٹرز کی معلومات) ، ایکسچینج سیکرٹ کیز وغیرہ۔

اس معلومات کی بنیاد پر ، ایک عام پروٹوکول پروگرام ایکسچینج انٹرفیس تک رسائی حاصل کرسکتا ہے ، مطلوبہ ڈیٹا حاصل کرسکتا ہے یا کچھ کام انجام دے سکتا ہے۔

عام طور پر ایکسچینج انٹرفیس میں طریقہ کار جیسے GET / POST / PUT / DELETE ہوتے ہیں ، جن میں عوامی انٹرفیس اور نجی انٹرفیس ہوتے ہیں۔

  • عوامی انٹرفیس: بغیر دستخط کی تصدیق کے انٹرفیس ، جنرل پروٹوکول کے طریقہ کار میں براہ راست درخواستیں۔
  • نجی انٹرفیس: انٹرفیس جس میں دستخط کی توثیق کی ضرورت ہوتی ہے ، جنرل پروٹوکول کے عمل میں دستخط کو نافذ کرنے کی ضرورت ہوتی ہے ، اور پھر ان تبادلے کے API انٹرفیس کی درخواست کی جاتی ہے۔

جنرل پروٹوکول پروسیسرز کو ایکسچینج انٹرفیس کے جوابات کے اعداد و شمار موصول ہوتے ہیں ، جن کو مزید پروسیسنگ کے لئے استعمال کیا جاتا ہے ، جس سے منتظمین کی توقع ہوتی ہے ((نیچے بیان کیا گیا ہے) ۔ حوالہ OKX فوری تبادلہ، پیتھون جنرل پروٹوکول مثال میں CustomProtocolOKX کلاس عمل درآمد میںGetTickerGetAccountمساوی افعال۔

5، جنرل پروٹوکول پروسیسر ڈیٹا کو منتظمین کو جواب دیتا ہے

جب جنرل پروٹوکول پروگرامز ایکسچینج کے API انٹرفیس تک رسائی حاصل کرتے ہیں، کچھ کارروائی کرتے ہیں یا کچھ ڈیٹا حاصل کرتے ہیں، تو انہیں منتظمین کو نتائج کی رائے دینے کی ضرورت ہوتی ہے.

پالیسی کال کرنے والے انٹرفیس پر منحصر ہے ، ہاسپٹروں کو فیڈ بیک کے اعداد و شمار مختلف ہوتے ہیں ، پہلے دو بڑی اقسام میں تقسیم کیا جاتا ہے:

  • جنرل پروٹوکول کے ذریعے تبادلوں کے انٹرفیس کو کال کرنے میں کامیابی:

    {
        "data": null,  // "data" can be of any type 
        "raw": null    // "raw" can be of any type 
    }
    
    • data: اس فیلڈ کا مخصوص ڈھانچہ اور جنرل پروٹوکول کے ذریعہ موصول ہونے والی درخواستوں میںmethodمتعلقہ، ایف ایم زیڈ پلیٹ فارم API افعال کی تعمیر کے لئے استعمال کیا جاتا ہے جس کے آخر میں واپس آنے والے اعداد و شمار کی ساخت، ذیل میں تمام انٹرفیس کی ایک فہرست ہے.
    • raw: یہ فیلڈ ایکسچینج API انٹرفیس کے جوابات کا خام ڈیٹا منتقل کرسکتا ہے ، جیسےexchange.GetTicker()فنکشن ٹکر ڈھانچہ، ٹکر ڈھانچے کے انفو فیلڈ میں ریکارڈ کیا جاتا ہے واپس آتا ہےrawکھیتوں اورdataاس کے علاوہ ، آپ کو اس کے بارے میں مزید جاننے کی ضرورت ہوگی۔
  • جنرل پروٹوکول کے عمل کو کال کرنے والے ایکسچینج انٹرفیس میں ناکامی (آپریشن کی خرابی، نیٹ ورک کی خرابی وغیرہ)

    {
        "error": ""    // "error" contains an error message as a string
    }
    
    • error: غلطی کا پیغام ، جو کہ صفحہ لاگ ان کے علاقوں جیسے کہ ایف ایم زیڈ پلیٹ فارم ڈسک ، ڈیبگنگ ٹولز وغیرہ میں ظاہر ہوتا ہے۔

ڈیمو سٹریٹجی پروگرام کے ذریعہ موصول ہونے والے جنرل پروٹوکول کے جوابات کے اعداد و شمار:

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

img

6، جنرل پروٹوکول میں ڈیٹا کی ساخت کے معاہدے

مذکورہ بالا ایک مختصر عمل ہے جس میں جنرل پروٹوکول کے پروگرامرز نے ایف ایم زیڈ غیر پیکڈ تک رسائی حاصل کرنے کے لئے تبادلہ API میں حصہ لیا ہے۔ اس عمل میں صرف ایف ایم زیڈ پلیٹ فارم ڈیبگنگ ٹول میں کال کرنے کی وضاحت کی گئی ہے۔exchange.GetTicker()فنکشن کے وقت کا عمل۔ ذیل میں تمام پلیٹ فارم API افعال کے ساتھ تعامل کی تفصیلات بیان کی جائیں گی۔

پلیٹ فارم نے مختلف تبادلے کے مشترکہ افعال کو ایک فنکشن میں متحد کیا ہے ، جیسے گیٹ ٹکر فنکشن ، جو موجودہ قسم کی مارکیٹ کی معلومات کی درخواست کرتا ہے ، جو بنیادی طور پر تمام تبادلے کے پاس موجود API ہے۔ لہذا جب پالیسی کی مثال میں پلیٹ فارم کے احاطہ کردہ API انٹرفیس تک رسائی حاصل کی جاتی ہے تو ، منتظم "عام پروٹوکول" پلگ ان کو درخواست بھیجتا ہے (جو پہلے ذکر کیا گیا ہے):

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

جب پالیسیوں میں مختلف موجد پلیٹ فارم کے احاطہ کردہ API افعال کو بلایا جاتا ہے (مثال کے طور پر ، گیٹ ٹکر) ، تو میزبانوں کے ذریعہ جنرل پروٹوکول کو بھیجے جانے والے درخواست کی شکل بھی مختلف ہوتی ہے۔methodاورparams◄ جنرل پروٹوکول کی تشکیلmethodاس کے علاوہ ، آپ کو انٹرفیس کے بارے میں جاننے کی ضرورت ہوگی کہ انٹرفیس کے بارے میں کیا ہے۔

فوری تبادلہ

مثال کے طور پر، موجودہ ٹریڈنگ جوڑی:ETH_USDTاس کے بعد مزید وضاحت نہیں کی جاتی ہے۔ منتظمین جنرل پروٹوکول کے جوابات کی توقع کرتے ہیں وہ بنیادی طور پر ڈیٹا فیلڈ میں لکھے جاتے ہیں ، یا ایک خام فیلڈ بھی شامل کی جاسکتی ہے جو ایکسچینج انٹرفیس کے اصل ڈیٹا کو ریکارڈ کرتی ہے۔

  • گیٹ ٹکر

    • 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]
                  // ... 
              ]
          }
      }
      
  • گیٹ ٹریڈز

    • طریقہ فیلڈ: trades
    • 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",
              }
              // ...
          ]
      }
      
  • ریکارڈ حاصل کریں

    • 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],
                  // ...
          ]
      }
      
  • گیٹ مارکیٹسعمل میں لانا

    • طریقہ فیلڈ:""
    • params فیلڈ:
      {}
      
    • اس کے علاوہ، یہ بھی کہا جاتا ہے کہ یہ ایک بہت بڑا مسئلہ ہے.
      {}
      
  • GetTickersعمل میں لانا

    • طریقہ فیلڈ:""
    • 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"
          }
      }
      
  • حاصل احکامات

    • 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
          }
      }
      
  • حاصل کریںHistoryOrders

    • طریقہ فیلڈ: historyorders
    • 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 应答的数据
      }
      
  • دیگر حکمت عملی کی مثال میں استعمال ہونے والے دیگر موجد پلیٹ فارم API افعال ، جیسے:exchange.Go()exchange.GetRawJSON()اس طرح کے افعال کو کسی بھی طرح کی ضرورت نہیں ہے، کال کرنے کا طریقہ، افعال تبدیل نہیں ہوتے ہیں۔

فیوچر ایکسچینج

فیوچر ایکسچینج تمام فیوچر ایکسچینج کے افعال کی حمایت کرتا ہے ، اس کے علاوہ کچھ فیوچر ایکسچینج کے مخصوص API افعال ہیں۔

عمل میں لانا

  • پوزیشن حاصل کریں
  • مارجن لیول سیٹ کریں
  • GetFundings

پیتھون ورژن کا عمومی پروٹوکول نمونہ

REST جنرل پروٹوکول ٹن OKX ایکسچینج REST API انٹرفیس تک رسائی حاصل کرتا ہے ، اور اسے فوری طور پر تبادلہ کرنے والے اشیاء کے طور پر پیک کیا جاتا ہے۔ ایک عوامی انٹرفیس کے لئے درخواست اور جواب کے اعداد و شمار کو لپیٹنے کا عمل۔ ایک نجی انٹرفیس کے ساتھ دستخط، درخواست اور جواب کے اعداد و شمار کو احاطہ کرتا ہے. یہ نمونہ بنیادی طور پر ٹیسٹنگ سیکھنے پر مبنی ہے ، باقی انٹرفیسز ماڈلنگ کے اعداد و شمار کا استعمال کرتے ہوئے براہ راست میزبانوں کو جواب دیتے ہیں ، جو ٹیسٹنگ کے لئے استعمال ہوتے ہیں۔

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()

مزید