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

FMZ کوانٹ ٹریڈنگ پلیٹ فارم کسٹم پروٹوکول رسائی گائیڈ

مصنف:FMZ~Lydia, تخلیق: 2024-11-08 16:37:25, تازہ کاری: 2024-11-19 13:31:01

img

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

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

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

1۔ تبادلہ کی تشکیل کریں

ایف ایم زیڈ کوانٹ ٹریڈنگ پلیٹ فارم پر ایکسچینج کی تشکیل کے لئے صفحہ:

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

img

  • پروٹوکول منتخب کریں: کسٹم پروٹوکول منتخب کریں.
  • سروس ایڈریس: کسٹم پروٹوکول پروگرام بنیادی طور پر ایک آر پی سی سروس ہے۔ لہذا ، تبادلے کی تشکیل کرتے وقت سروس ایڈریس اور پورٹ کو واضح طور پر متعین کرنا ضروری ہے۔ اس طرح ، ڈوکر جانتا ہے کہ عمل کے دوران کسٹم پروٹوکول پروگرام تک کہاں رسائی حاصل کی جائے۔Strategy instance running on the docker -> Custom protocol program. مثلاً:http://127.0.0.1:6666/OKX، کسٹم پروٹوکول پروگرام اور ڈوکر عام طور پر ایک ہی ڈیوائس (سرور) پر چلتے ہیں ، لہذا سروس ایڈریس کو مقامی مشین (لوکل ہوسٹ) کے طور پر لکھا جاتا ہے ، اور بندرگاہ کو اس بندرگاہ کے طور پر استعمال کیا جاسکتا ہے جو نظام کے ذریعہ مقیم نہیں ہے۔
  • رسائی کی چابی: عمل کے دوران منتقل تبادلہ ترتیب کی معلوماتStrategy instance running on the docker -> Custom protocol program.
  • خفیہ کلید: عمل کے دوران منتقل تبادلہ ترتیب کی معلوماتStrategy instance running on the docker -> Custom protocol program.
  • ٹیگ: ایف ایم زیڈ کوانٹ ٹریڈنگ پلیٹ فارم پر ایکسچینج آبجیکٹ کا ٹیگ، جس کا استعمال کسی مخصوص ایکسچینج آبجیکٹ کی شناخت کے لیے کیا جاتا ہے۔

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

img

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

accessKey:  accesskey123    // accesskey123, these are not actual keys, just for demonstration
secretKey:  secretkey123
passphrase: passphrase123

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

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

3. حکمت عملی مثال FMZ API تقریب کی درخواست کرتا ہے

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

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

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

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

فنکشن کو کال کرناexchange.GetTicker()، اپنی مرضی کے مطابق پروٹوکول پروگرام کی درخواست موصول:

POST /OKX HTTP/1.1 
{
    "access_key":"xxx",
    "method":"ticker",
    "nonce":1730275031047002000,
    "params":{"symbol":"LTC_USDT"},
    "secret_key":"xxx"
}
  • access_key: تبادلہ کلید اوپر پلیٹ فارم Configure Exchange میں تشکیل
  • secret_key: تبادلہ کی چابی اوپر پلیٹ فارم Configure Exchange میں ترتیب دی گئی ہے
  • طریقہ: حکمت عملی میں کال کرنے والے انٹرفیس سے متعلق، جب کال کریںexchange.GetTicker(), methodہےticker.
  • nonce: اس وقت کا ٹائم اسٹیمپ جب درخواست کی گئی۔
  • پیرامیٹرز: اس مثال میں حکمت عملی میں انٹرفیس کال سے متعلق پیرامیٹرز، جب کال کریںexchange.GetTicker()، متعلقہ پیرامیٹرز ہیں:{"symbol":"LTC_USDT"}.

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

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

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

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

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

کسٹم پروٹوکول پروگرام تبادلہ انٹرفیس سے جواب کے اعداد و شمار وصول کرتا ہے اور ڈوکر کے ذریعہ متوقع اعداد و شمار کی تعمیر کے ل further اسے مزید پروسیس کرتا ہے (جو ذیل میں بیان کیا گیا ہے) ۔ OKX اسپاٹ ایکسچینج کا حوالہ دیں ،GetTicker, GetAccountاور پیتھون کسٹم پروٹوکول مثال میں کسٹم پروٹوکول او ایکس ایکس کلاس کے نفاذ میں دیگر افعال۔

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

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

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

  • اپنی مرضی کے مطابق پروٹوکول پروگرام تبادلہ انٹرفیس کو کامیابی سے بلاتا ہے:
{
    "data": null,  // "data" can be of any type 
    "raw": null    // "raw" can be of any type 
}

اعداد و شمار: اس فیلڈ کی مخصوص ساختmethodکسٹم پروٹوکول پروگرام کے ذریعہ موصولہ درخواست میں ، اور ایف ایم زیڈ پلیٹ فارم API فنکشن کے ذریعہ بالآخر واپس آنے والے ڈیٹا ڈھانچے کی تعمیر کے لئے استعمال ہوتا ہے۔ تمام انٹرفیس ذیل میں درج ہوں گے۔ خام: اس فیلڈ کو ایکسچینج API انٹرفیس کے جواب کے خام ڈیٹا میں منتقل کرنے کے لئے استعمال کیا جاسکتا ہے ، جیسے ٹکر ڈھانچہexchange.GetTicker()فنکشن۔ ٹکر ڈھانچے کا انفو فیلڈ ڈیٹا کو ریکارڈ کرتا ہےrawمیدان اورdataفیلڈ؛ کچھ پلیٹ فارم API افعال کو اس ڈیٹا کی ضرورت نہیں ہے۔

  • کسٹم پروٹوکول پروگرام ایکسچینج انٹرفیس کو کال کرنے میں ناکام رہا (کاروباری غلطی ، نیٹ ورک کی غلطی ، وغیرہ)
{
    "error": ""    // "error" contains an error message as a string
}

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

حکمت عملی پروگرام کی طرف سے موصول اپنی مرضی کے مطابق پروٹوکول ردعمل کے اعداد و شمار کا مظاہرہ کرتا ہے:

// Tested in the debugging tool of the FMZ platform
function main() {
    Log(exchange.GetTicker("USDT"))       // The trading pair is incomplete, the BaseCurrency part is missing, and the custom protocol plug-in is required to return an error message: {"error": "..."}
    Log(exchange.GetTicker("LTC_USDT"))
}

img

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

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

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

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

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

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

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

  • گیٹ ٹکر

طریقہ کار کا میدان: ticker پیرامس فیلڈ:

{"symbol":"ETH_USDT"}

ڈیٹا جو ڈاکر اپنی مرضی کے مطابق پروٹوکول جواب میں توقع کرتا ہے:

{
    "data": {
        "symbol": "ETH_USDT",      // Corresponds to the Symbol field in the Ticker structure returned by the GetTicker function
        "buy": "2922.18",          // ...corresponds to the Buy field
        "sell": "2922.19", 
        "high": "2955", 
        "low": "2775.15", 
        "open": "2787.72", 
        "last": "2922.18", 
        "vol": "249400.888156", 
        "time": "1731028903911"
    },
    "raw": {}                      // A raw field can be added to record the raw data of the exchange API interface response
}
  • گہرائی حاصل کریں

طریقہ کار کا میدان: گہرائی پیرامس فیلڈ:

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

طریقہ کار کا میدان: تجارتیں پیرامس فیلڈ:

{"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",
        }
        // ...
    ]
}
  • ریکارڈ حاصل کریں

طریقہ کار فیلڈ: ریکارڈز پیرامس فیلڈ:

{
    "limit":"500",
    "period":"60",          // 60 minutes
    "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],
            // ...
    ]
}
  • گیٹ مارکیٹسلاگو کیا جائے

طریقہ کار کا میدان: پیرامس فیلڈ:

{}

ڈیٹا جو ڈاکر اپنی مرضی کے مطابق پروٹوکول جواب میں توقع کرتا ہے:

{}
  • GetTickersلاگو کیا جائے

طریقہ کار کا میدان: پیرامس فیلڈ:

{}

ڈیٹا جو ڈاکر اپنی مرضی کے مطابق پروٹوکول جواب میں توقع کرتا ہے:

{}
  • اکاؤنٹ حاصل کریں

طریقہ کار کا میدان: حسابات پیرامس فیلڈ:

{}

ڈیٹا جو ڈاکر اپنی مرضی کے مطابق پروٹوکول جواب میں توقع کرتا ہے:

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

طریقہ کار کا میدان: اثاثہ جات پیرامس فیلڈ:

{}

ڈیٹا جو ڈاکر اپنی مرضی کے مطابق پروٹوکول جواب میں توقع کرتا ہے:

{
    "data": [
        {"currency": "TUSD", "free": "3000", "frozen": "0"},
        {"currency": "BTC", "free": "0.2482982056277609", "frozen": "0"}, 
        // ...
    ]
}
  • تخلیق آرڈر / خرید / فروخت

طریقہ کار کا میدان: تجارت پیرامس فیلڈ:

{"amount":"0.1","price":"1000","symbol":"BTC_USDT","type":"buy"}

ڈیٹا جو ڈاکر اپنی مرضی کے مطابق پروٹوکول جواب میں توقع کرتا ہے:

{
    "data": {
        "id": "BTC-USDT,123456"
    }
}
  • حاصل احکامات

طریقہ کار کا میدان: آرڈر پیرامس فیلڈ:

{"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"
        }, 
        // ...
    ]
}
  • آرڈر حاصل کریں

طریقہ فیلڈ: آرڈر پیرامس فیلڈ:

{
    "id":"ETH-USDT,123456",       // Calling in the strategy: 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,         // If the exchange does not provide it, it can be assigned a value of 0 during processing.
    }
}
  • حاصل کریںHistoryOrders

طریقہ فیلڈ: تاریخ کے احکامات پیرامس فیلڈ:

{"limit":0,"since":0,"symbol":"ETH_USDT"}

ڈیٹا جو ڈاکر اپنی مرضی کے مطابق پروٹوکول جواب میں توقع کرتا ہے:

{
    "data": [
        {
            "id": "ETH-USDT,123456",
            "symbol": "ETH_USDT",
            "amount": 0.25,
            "price": 1005,
            "deal_amount": 0,
            "avg_price": 1000,
            "type": "buy",       // "buy"、"sell"
            "status": "filled",  // "filled"
        }, 
        // ...
    ]
}
  • آرڈر منسوخ کریں

طریقہ فیلڈ: منسوخ کریں پیرامس فیلڈ:

{"id":"ETH-USDT,123456","symbol":"ETH_USDT"}

ڈیٹا جو ڈاکر اپنی مرضی کے مطابق پروٹوکول جواب میں توقع کرتا ہے:

{
    "data": true    // As long as there is no error field in the JSON, the order cancellation is considered successful by default.
}
  • آئی او

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

// Called in the strategy instance
exchange.IO("api", "GET", "/api/v5/trade/orders-pending", "instType=SPOT&instId=ETH-USDT")

طریقہ کار کا میدان:"__api_/api/v5/trade/orders-pending"، طریقہ فیلڈ _ سے شروع ہوتا ہےایپی، اس بات کا اشارہ ہے کہ اس کی وجہ سےexchange.IOحکمت عملی مثال میں فنکشن کال. پیرامس فیلڈ:

{"instId":"ETH-USDT","instType":"SPOT"}   // instType=SPOT&instId=ETH-USDT encoded parameters will be restored to JSON

ڈیٹا جو ڈاکر اپنی مرضی کے مطابق پروٹوکول جواب میں توقع کرتا ہے:

{
    "data": {"code": "0", "data": [], "msg": ""}    // The data attribute value is the data of the exchange API: GET /api/v5/trade/orders-pending response
}
  • دیگر حکمت عملی کی مثالوں میں استعمال ہونے والے دیگر ایف ایم زیڈ پلیٹ فارم API افعال ، جیسے:exchange.Go(), exchange.GetRawJSON()اور دیگر افعال کو انکیپسول کرنے کی ضرورت نہیں ہے، اور کال کرنے کا طریقہ اور فنکشن تبدیل نہیں ہوتے ہیں۔

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

اسپاٹ ایکسچینجز کے تمام افعال کی حمایت کرنے کے علاوہ ، فیوچر ایکسچینجز میں کچھ API افعال بھی ہیں جو فیوچر ایکسچینجز کے لئے منفرد ہیں۔

لاگو کیا جائے

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

پیتھون ورژن میں اپنی مرضی کے مطابق پروٹوکول مثال

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

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

مزید