Type/to search
8
Follow
1363
Followers
موجد مقداری تجارتی پلیٹ فارم جنرل پروٹوکول رسائی گائیڈ
Discussions
Created 2024-10-29 14:37:56  Updated 2024-11-12 21:58:55
 0
 1361

img

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

یہ مضمون کرے گاRESTپروٹوکول تک رسائی کو ایک مثال کے طور پر لیتے ہوئے، یہ بتاتا ہے کہ OKX ایکسچینج کے API کو سمیٹنے اور اس تک رسائی حاصل کرنے کے لیے Inventor Quantitative Trading Platform کے عمومی پروٹوکول کو کیسے استعمال کیا جائے۔ جب تک کہ دوسری صورت میں وضاحت نہ کی گئی ہو، یہ مضمون REST جنرل پروٹوکول کا حوالہ دیتا ہے۔

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

1. ایکسچینج کو ترتیب دیں۔

موجد مقداری تجارتی پلیٹ فارم پر تبادلے کو ترتیب دینے کا صفحہ:

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

img

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

مضمون میں ظاہر کردہ OKX پلگ ان کنفیگریشن کا اسکرین شاٹ درج ذیل ہے:

img

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

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

2. نگران کی تعیناتی اور یونیورسل پروٹوکول پروگرام (پلگ ان)

    1. میزبان
      انوینٹر کوانٹیٹیو ٹریڈنگ پلیٹ فارم پر کسی بھی حقیقی وقت کی حکمت عملی کو چلانے کے لیے، آپ کو ایک نگران تعینات کرنا چاہیے، براہ کرم پلیٹ فارم ٹیوٹوریل کا حوالہ دیں، جسے یہاں دہرایا نہیں جائے گا۔
    1. جنرل پروٹوکول پروگرام (پلگ ان)
      ہوسٹ اور یونیورسل پروٹوکول کو عام طور پر ایک ہی ڈیوائس پر لگایا جاتا ہے۔ یہ مضمون Python3 میں لکھا جا سکتا ہے۔ کسی بھی Python پروگرام کو چلانے کی طرح، آپ اسے براہ راست انجام دے سکتے ہیں (پائیتھون ماحول کی مختلف کنفیگریشنز پہلے سے بنائیں)۔
      بلاشبہ، FMZ Python پروگراموں کو چلانے کی بھی حمایت کرتا ہے، اور یہ عام پروٹوکول ایک حقیقی ڈسک کے طور پر چلایا جا سکتا ہے تاکہ موجد کے مقداری تجارتی پلیٹ فارم کو بغیر پیکج شدہ ایکسچینج API تک رسائی کے لیے تعاون فراہم کیا جا سکے۔
      عام پروٹوکول پروگرام چلنے کے بعد، نگرانی شروع کریں:http://127.0.0.1:6666عام پروٹوکول پروگرام میں، مخصوص راستے بتائے جا سکتے ہیں، مثال کے طور پر/OKXعملدرآمد کیا جائے.

3. حکمت عملی مثال FMZ API فنکشن کی درخواست کرتی ہے۔

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

ڈیبگنگ ٹولز کا صفحہ:

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

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

کال کریں۔exchange.GetTicker()فنکشن، جنرل پروٹوکول پروگرام کو درخواست موصول ہوتی ہے:

http
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: ٹائم اسٹیمپ جب درخواست ہوئی تھی۔
  • params: پالیسی میں انٹرفیس کال سے متعلق پیرامیٹرز۔exchange.GetTicker()کال کرتے وقت، متعلقہ پیرامیٹرز یہ ہیں:{"symbol":"LTC_USDT"}

4. جنرل پروٹوکول پروگرام ایکسچینج انٹرفیس تک رسائی

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

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

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

  • عوامی انٹرفیس: ایک انٹرفیس جس میں دستخطی تصدیق کی ضرورت نہیں ہوتی ہے اور اس کی براہ راست درخواست ایک عام پروٹوکول پروگرام میں کی جاتی ہے۔
  • پرائیویٹ انٹرفیس: ایک انٹرفیس جس میں دستخط کی تصدیق کی ضرورت ہوتی ہے ان ایکسچینجز کے API انٹرفیس کی درخواست کرنے کے لیے دستخط کو عام پروٹوکول پروگرام میں لاگو کرنے کی ضرورت ہوتی ہے۔

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

5. جنرل پروٹوکول پروگرام کسٹوڈین کو ڈیٹا کا جواب دیتا ہے۔

جب عام پروٹوکول پروگرام ایکسچینج کے API انٹرفیس تک رسائی حاصل کرتا ہے، کچھ آپریشن کرتا ہے یا کچھ ڈیٹا حاصل کرتا ہے، تو اسے نتائج کو محافظ کو واپس کرنے کی ضرورت ہوتی ہے۔

نگہبان کو دیا گیا ڈیٹا حکمت عملی کے ذریعے بلائے گئے انٹرفیس کے مطابق مختلف ہوتا ہے، اور اسے پہلے دو قسموں میں تقسیم کیا جاتا ہے:

  • جنرل پروٹوکول پروگرام کامیابی کے ساتھ ایکسچینج انٹرفیس کو کال کرتا ہے:

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

    json
    { "error": "" // "error" contains an error message as a string }
    • ایرر: ایرر کی معلومات، جو (FMZ) پلیٹ فارم ریئل ڈسک، ڈیبگنگ ٹول اور دیگر صفحات کے لاگ ایریا میں ایرر لاگ میں ظاہر ہوگی۔

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

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

img

6. عام پروٹوکول میں ڈیٹا ڈھانچہ کا معاہدہ

مندرجہ بالا ایک مختصر عمل ہے کہ کس طرح عام پروٹوکول پروگرام (FMZ unpackaged) ایکسچینج API تک رسائی حاصل کرتا ہے یہ عمل صرف اس بات کی وضاحت کرتا ہے کہ (FMZ) پلیٹ فارم ڈیبگنگ ٹول کو کیسے کال کرنا ہے۔exchange.GetTicker()فنکشن کا عمل۔ اس کے بعد، تمام پلیٹ فارم API فنکشنز کے تعامل کی تفصیلات کو تفصیل سے بیان کیا جائے گا۔

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

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

حکمت عملی میں مختلف موجد پلیٹ فارم encapsulated API فنکشنز کو کال کرتے وقت (جیسے GetTicker)، نگران کی طرف سے جنرل پروٹوکول کو بھیجی جانے والی درخواست کی شکل بھی مختلف ہوگی۔ جسم میں ڈیٹا (JSON) صرف اس میں مختلف ہے۔methodاورparams. عام پروٹوکول کو ڈیزائن کرتے وقت،methodآپ مواد کی بنیاد پر مخصوص آپریشن کر سکتے ہیں۔ مندرجہ ذیل تمام انٹرفیس کے لیے درخواست کے جواب کے منظرنامے ہیں۔

اسپاٹ ایکسچینج

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

  • GetTicker

    • طریقہ کا میدان: "ٹکر"

    • پیرامز فیلڈ:

      json
      {"symbol":"ETH_USDT"}
    • وہ ڈیٹا جس کی میزبان کو عام پروٹوکول کے جواب میں توقع ہے:

      json
      { "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

    • طریقہ کا میدان: "گہرائی"

    • پیرامز فیلڈ:

      json
      {"limit":"30","symbol":"ETH_USDT"}
    • وہ ڈیٹا جس کی میزبان کو عام پروٹوکول کے جواب میں توقع ہے:

      json
      { "data" : { "time" : 1500793319499, "asks" : [ [1000, 0.5], [1001, 0.23], [1004, 2.1] // ... ], "bids" : [ [999, 0.25], [998, 0.8], [995, 1.4] // ... ] } }
  • GetTrades

    • طریقہ کا میدان: "تجارت"

    • پیرامز فیلڈ:

      json
      {"symbol":"eth_usdt"}
    • وہ ڈیٹا جس کی میزبان کو عام پروٹوکول کے جواب میں توقع ہے:

      json
      { "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

    • طریقہ کا میدان: "ریکارڈز"

    • پیرامز فیلڈ:

      json
      { "limit":"500", "period":"60", // 60分钟 "symbol":"ETH_USDT" }
    • وہ ڈیٹا جس کی میزبان کو عام پروٹوکول کے جواب میں توقع ہے:

      json
      { "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
    عمل میں لایا جائے۔

    • طریقہ کا میدان: ""

    • پیرامز فیلڈ:

      json
      {}
    • وہ ڈیٹا جس کی میزبان کو عام پروٹوکول کے جواب میں توقع ہے:

      json
      {}
  • GetTickers
    عمل میں لایا جائے۔

    • طریقہ کا میدان: ""

    • پیرامز فیلڈ:

      json
      {}
    • وہ ڈیٹا جس کی میزبان کو عام پروٹوکول کے جواب میں توقع ہے:

      json
      {}
  • GetAccount

    • طریقہ کا میدان: "اکاؤنٹس"

    • پیرامز فیلڈ:

      json
      {}
    • وہ ڈیٹا جس کی میزبان کو عام پروٹوکول کے جواب میں توقع ہے:

      json
      { "data": [ {"currency": "TUSD", "free": "3000", "frozen": "0"}, {"currency": "BTC", "free": "0.2482982056277609", "frozen": "0"}, // ... ] }
  • GetAssets

    • طریقہ کا میدان: "اثاثے"

    • پیرامز فیلڈ:

      json
      {}
    • وہ ڈیٹا جس کی میزبان کو عام پروٹوکول کے جواب میں توقع ہے:

      json
      { "data": [ {"currency": "TUSD", "free": "3000", "frozen": "0"}, {"currency": "BTC", "free": "0.2482982056277609", "frozen": "0"}, // ... ] }
  • CreateOrder / Buy / Sell

    • طریقہ کا میدان: "تجارت"

    • پیرامز فیلڈ:

      json
      {"amount":"0.1","price":"1000","symbol":"BTC_USDT","type":"buy"}
    • وہ ڈیٹا جس کی میزبان کو عام پروٹوکول کے جواب میں توقع ہے:

      json
      { "data": { "id": "BTC-USDT,123456" } }
  • GetOrders

    • طریقہ کا میدان: "احکامات"

    • پیرامز فیلڈ:

      json
      {"symbol":"ETH_USDT"}
    • وہ ڈیٹا جس کی میزبان کو عام پروٹوکول کے جواب میں توقع ہے:

      json
      { "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

    • طریقہ کا میدان: "آرڈر"

    • پیرامز فیلڈ:

      json
      { "id":"ETH-USDT,123456", // 策略中调用:exchange.GetOrder("ETH-USDT,123456") "symbol":"ETH_USDT" }
    • وہ ڈیٹا جس کی میزبان کو عام پروٹوکول کے جواب میں توقع ہے:

      json
      { "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

    • طریقہ کا میدان: "ہسٹری آرڈرز"

    • پیرامز فیلڈ:

      json
      {"limit":0,"since":0,"symbol":"ETH_USDT"}
    • وہ ڈیٹا جس کی میزبان کو عام پروٹوکول کے جواب میں توقع ہے:

      json
      { "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

    • طریقہ کا میدان: "منسوخ کریں"

    • پیرامز فیلڈ:

      json
      {"id":"ETH-USDT,123456","symbol":"ETH_USDT"}
    • وہ ڈیٹا جس کی میزبان کو عام پروٹوکول کے جواب میں توقع ہے:

      json
      { "data": true // 只要该JSON中没有error字段,都默认为撤单成功 }
  • IO

    Exchange.IO فنکشن کو براہ راست ایکسچینج انٹرفیس تک رسائی حاصل کرنے کے لیے استعمال کیا جاتا ہے، مثال کے طور پر، ہم استعمال کرتے ہیں۔GET /api/v5/trade/orders-pending, 参数:instType=SPOT,instId=ETH-USDTمثال کے طور پر۔

    javascript
    // 策略实例中调用 exchange.IO("api", "GET", "/api/v5/trade/orders-pending", "instType=SPOT&instId=ETH-USDT")
    • طریقہ کا میدان:"__api_/api/v5/trade/orders-pending"میتھڈ فیلڈ _api سے شروع ہوتی ہے، جو اس بات کی نشاندہی کرتی ہے کہ یہ حکمت عملی مثال میں exchange.IO فنکشن کال کے ذریعے متحرک ہے۔

    • پیرامز فیلڈ:

      json
      {"instId":"ETH-USDT","instType":"SPOT"} // instType=SPOT&instId=ETH-USDT编码的参数会被还原为JSON
    • وہ ڈیٹا جس کی میزبان کو عام پروٹوکول کے جواب میں توقع ہے:

      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["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()
Comment
All comments (0)
No data
No data
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)