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

مصنف:لیدیہ, تخلیق: 2023-07-12 15:29:54, تازہ کاری: 2024-01-03 21:01:07

img

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

اپنی مرضی کے مطابق پروٹوکول استعمال کی دستاویزات

آپ اس عام پروٹوکول کو کسی بھی تبادلے تک رسائی حاصل کرنے کے لئے استعمال کر سکتے ہیں جو API ٹریڈنگ فراہم کرتا ہے، مخصوص API پروٹوکول محدود نہیں ہے، چاہے وہ آرام، ویب ساکٹ، درست کریں... پائیتھون اپنی مرضی کے مطابق پروٹوکول مثال:https://www.fmz.com/strategy/101399

اپنی مرضی کے مطابق پروٹوکول پلگ ان آپریشن، بندرگاہ کی ترتیبات

کسٹم پروٹوکول پلگ ان کے سننے والے ایڈریس اور پورٹ کی ترتیب مندرجہ ذیل ہوسکتی ہے: مثلاً:http://127.0.0.1:6666/DigitalAssetیاhttp://127.0.0.1:6666/exchange.

ہمیں ان کو سیٹ کرنے کی ضرورت کیوں ہےآئی پیاورراہیں؟ یہ اس لئے ہے کیونکہ جبتبادلہ شامل کرناصفحہ میںFMZ کوانٹ پلیٹ فارم ڈیش بورڈ کسٹم پروٹوکول آپشن کو منتخب کرنے سے سروس ایڈریسAPI-KEY. یہ سروس ایڈریس ڈوکر کو بتاتا ہے کہ آئی پی اور پورٹ تک کہاں رسائی حاصل کی جائے (ڈوکر اور کسٹم پروٹوکول پلگ ان پروگرام ایک ہی ڈیوائس پر چل نہیں سکتے ہیں) ۔ مثال کے طور پر سروس ایڈریس کے طور پر بھرا جا سکتا ہےhttp://127.0.0.1:6666/DigitalAsset. DigitalAssetصرف ایک مثال ہے اور آپ کی پسند کا نام کے ساتھ تبدیل کیا جا سکتا ہے.

FMZ کوانٹ پلیٹ فارم s ایڈ ایکسچینج صفحے پر، عام طور پر تبادلہ ترتیب صرف کی ضرورت ہوتی ہےaccess keyاورsecret keyتاہم ، کچھ تبادلے API انٹرفیس کے لئے تجارتی پاس ورڈ کو منتقل کرنے کی ضرورت ہوتی ہے (جیسے ، کچھ تبادلے کے آرڈر کی جگہ کا انٹرفیس) ۔ ایسے معاملات میں ، چونکہ کسٹم پروٹوکول پیج میں اس معلومات کو داخل کرنے کے لئے اضافی کنٹرولز نہیں ہیں ، لہذا ہم اضافی ضرورت کی تشکیل کی معلومات کو شامل کرسکتے ہیںsecret key(یاaccess keyاگر معلومات حساس نہیں ہیں). پھر، اپنی مرضی کے مطابق پروٹوکول پلگ ان پروگرام میں، ہم ایک تار انجام دے سکتے ہیںsplitاس اعداد و شمار کو الگ کرنے کے لئے آپریشن، مثال تصویر میں دکھایا گیا ہے.

img

اور پھر پلگ ان میں، حاصل کرنے کے لئے اس کا عملXXX_PassWord. مثال کے طور پر، اس پوسٹ کے آخر میں مکمل مثال میں، newBitgo فنکشن میں:

func newBitgo(accessKey, secretKey string) *iBitgo {
    s := new(iBitgo)
    s.accessKey = accessKey
    s.secretKey = secretKey
    // Additional configuration information in the secretKey can be separated here and can be written as in the following comment
    /*
    arr := strings.SplitN(secretKey, ",", 2)
    if len(arr) != 2 {
        panic("Configuration error!")
    }
    s.secretKey = arr[0]   // secret key 
    s.passWord = arr[1]    // XXX_PassWord
    */
    s.apiBase = "https://www.bitgo.cn"
    s.timeout = 20 * time.Second
    s.timeLocation = time.FixedZone("Asia/Shanghai", 8*60*60)

    return s
}

درخواست کے اعداد و شمار میں پیرامیٹرز کو دوبارہ تجزیہ کرتے ہوئے ، ڈوکر درخواست کے اعداد و شمار کو بطور بھیجتا ہے:

"secret_key" : "XXX",

پلگ ان اس قسم کی معلومات پر مشتمل آنے والے اعداد و شمار کو وصول کرتا ہے اور کوما علیحدگی پر مبنی XXX_PassWord کو اس سے الگ کرتا ہے ، تاکہ یہ اضافی منظور شدہ اعداد و شمار حاصل کرے۔

ایک مجموعی طور پر اپنی مرضی کے مطابق پروٹوکول پلگ ان کی مثالmainفنکشن:Goزبان کا بیان:

func main(){
    var addr = flag.String("b", "127.0.0.1:6666", "bing addr")   // Set command line parameters, default value description, port setting 6666
    flag.Parse()                                                 // Parsing the command line
    if *addr == "" {
        flag.Usage()                                             // Display the command line description
        return 
    }
    basePath := "/DigitalAsset"
    log.Println("Running ", fmt.Sprintf("http://%s%s", *addr, basePath), "...")   // Print listening port information
    http.HandleFunc(basePath, OnPost)
    http.ListenAndServe(*addr, nil)
}

جواب کی تقریب

کسٹم پروٹوکول پلگ ان پروگرام مسلسل آنے والے کے لئے ایک مخصوص بندرگاہ پر سننےrequestایک بار جب کوئی درخواست موصول ہوجاتی ہے تو ، یہ جواب دینے کے لئے رسپانس فنکشن کو کال کرتا ہے اور پھر درخواست کے اعداد و شمار سے پیرامیٹرز کو تجزیہ کرتا ہے۔ ڈوکر کے ذریعہ بھیجے جانے والے درخواست کے اعداد و شمار یہ ہیں:

/* JSON structure of request, FMZ Quant call GetTicker, docker sent to the custom protocol plugin case example (the value of params may be different for each API call, here the method is ticker):
{
    "access_key" : "XXX",               // `json:"access_key"`
    "secret_key" : "XXX",               // `json:"secret_key"`
    "nonce" : "1502345965295519602",    // `json:"nonce"`
    "method" : "ticker",                // `json:"method"`
    "params" : {                        // `json:"params"`
                   "symbol" : "btc",
                   ...
               },                       // The parameters are slightly different for each request. That is, different FMZ Quant APIs are called in the strategy with different parameters, which are described in the following sections for each API.
}
*/

تو، کی بنیاد پرMethodمیدان میںrequestJSON درخواست deserializing کی طرف سے حاصل کی ساخت جسم کے اعداد و شمار یونیورسل پروٹوکول پلگ ان پروگرام میں موصول، ہم ایک استعمال کر سکتے ہیںswitchمختلف FMZ Quant APIs کو ڈوکر پر بلایا جا رہا ہے کی درجہ بندی اور سنبھالنے کے لئے بیان (یعنی، جس FMZ Quant کی شناختAPIڈوکر پر چلنے والی حکمت عملی کا مطالبہ کر رہا ہے):

مثال میںGoزبان:

switch request.Method {    // M of request.Method is capitalized here, the body of the request received by the custom protocol program for the JSON data, in the Go language, the anti-JSON serialization (Unmarshal) is a structure, the first letter of the field must be capitalized
  case "accounts" :        // When the exchange.GetAccount() function is called in the bot strategy on the docker, the docker sends in a request where the Body carries data with a method attribute value of accounts
      data, err = e.GetAccount(symbol)
  case "ticker" :
      data, err = e.GetTicker(symbol)
  case "depth" :
      data, err = e.GetDepth(symbol)
  case "trades" :
      data, err = e.GetTrades(symbol)
  case "trade" :
  ...
  default:
      ...

ان شاخوں کو چلانے کے بعد ، واپس آنے والے ڈیٹا کو اس ڈھانچے میں لکھا جانا چاہئے جو کسٹم پروٹوکول پلگ ان پروگرام ڈوکر کی درخواست کا جواب دینے کے لئے استعمال کرے گا۔

گو زبان میں مثال:

defer func(){                                // Handling of closing work 
      if e := recover(); e != nil {          // The recover() function is used to catch panic, e ! = nil, i.e. an error has occurred
          if ee, ok := e.(error); ok {       // Type derivation, successful derivation assigns ee.Error() to e
              e = ee.Error()                 // Call the Error method to get the returned error string
          }
          ret = map[string]string{"error": fmt.Sprintf("%v", e)}
      }
      b, _ := json.Marshal(ret)              // Encode the result obtained from this call, ret, assign it to b, and write it into the response pointer
      w.Write(b)
      //fmt.Println("after w.Write the b is", string(b))     // test
  }()

3۔ API کالز کی اقسام

تقریباً دو اقسام میں تقسیم:

  1. عوامی انٹرفیس جن پر دستخط کی ضرورت نہیں ہوتی، مثال کے طور پر:

GetTicker()

GetDepth()

GetTrades()

GetRecords(period)

  1. صارف انٹرفیس جو سائن کرنے کی ضرورت ہے، جیسے:

Buy, Sell

GetOrder(id)

GetOrders()

GetAccount()

CancelOrder(id)... دستخط کے طریقے تبادلہ سے تبادلہ میں مختلف ہوسکتے ہیں ، اور ضروریات کے مطابق خاص طور پر لکھنے کی ضرورت ہے۔

مختلف ایف ایم زیڈ کوانٹ اے پی آئی انٹرفیس کو کال کرتے وقت کسٹم پروٹوکول پلگ ان اور ڈوکر کے مابین تعامل کے لئے ڈیٹا فارمیٹ:

کچھ FMZ Quant API انٹرفیس ، جیسے:GetName(), GetLabel()، وغیرہ، درخواستیں نہیں بھیجیںاپنی مرضی کے مطابق پروٹوکول پلگ انجب بلایا جائے۔ جب کال کریںexchange.GetName()، عالمگیر پلگ ان میں تشکیل تبادلہ Exchange واپس آئے گا.

    1. گیٹ ٹکر: موجودہ ٹکر ڈیٹا حاصل کرنے کے لئے استعمال کیا جاتا ہے.

کےmethodمیںrequestکی طرف سے بھیجاڈوکرسننے کے جواب کی تقریب ہےticker.

ڈاکر پیرامیٹر بھیجتا ہے:request.Params.symbol، جو روبوٹ کے صفحے پر مقرر کرنسی کی بنیاد پر ڈوکر کی طرف سے بھیجا جاتا ہے.

ڈیٹا فارمیٹ (JSON) درخواست جسم میں لے جایا جب ڈاکر اپنی مرضی کے مطابق پروٹوکول پلگ ان کی درخواست کرتا ہے

{
    "access_key" : "access_key",
    "secret_key" : "secret_key",
    "nonce" :      "1500793319499",            // millisecond timestamp
    "method" :     "ticker",
    "params" :     {"symbol" : "ETH_BTC"},     // Take the ETH_BTC trading pair for example
}

ڈاکر کو بھیجے گئے حتمی ریٹرن ویلیو کا ڈھانچہ: (یعنی وہ فارمیٹ جس میں مشترکہ پروٹوکول پلگ ان کے ذریعہ ایکسچینج انٹرفیس کی درخواست کے بعد ڈاکر کو ڈیٹا واپس کیا گیا ہے)

JSON ساخت

{
    "data": {
        "time": 1500793319499,  // Millisecond timestamp, integer
        "buy": 1000,            // floating-point type as follows
        "sell": 1001,
        "last": 1005,
        "high": 1100,
        "low": 980,
        "vol": 523,
    }
}
    1. GetRecords: تبادلہ کے ذریعہ فراہم کردہ K- لائن ڈیٹا کو بازیافت کرنے کے لئے استعمال کیا جاتا ہے۔ (ڈاکر کے ذریعہ درخواست کردہ پیرامیٹرز کی بنیاد پر)

کےmethodمیںrequestکی طرف سے بھیجا ڈاکر سننے کے جواب کی تقریب ہےrecords.

ڈاکر پیرامیٹرز بھیجتا ہے:request.Params.period، جس میں کی پہلی پیرامیٹر کے ساتھ منسلک ہےexchange.GetRecordsفنکشن. اصلrequest.Params.periodمنٹ میں مدت کی نمائندگی کرتا ہے. مثال کے طور پر روزانہ مدت ہے60*24، جو کہ ہے1440. request.Params.symbolمقررہ کرنسی کی بنیاد پر ڈاکر کی طرف سے بھیجا جاتا ہے.

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

{
    "access_key" : "access_key",
    "secret_key" : "secret_key",
    "nonce" :      "1500793319499",            // millisecond timestamp
    "method" :     "records",
    "params" :     {"symbol" : "ETH_BTC", "period" : "1440"},     // Example of an ETH_BTC pair with a daily K-period
}

ڈوکر کو بھیجے گئے حتمی واپسی کی قیمت کا ڈھانچہ:

JSON ساخت

{
    "data": [
            [1500793319, 1.1, 2.2, 3.3, 4.4, 5.5],         // "Time":1500793319000,"Open":1.1,"High":2.2,"Low":3.3,"Close":4.4,"Volume":5.5
            [1500793259, 1.01, 2.02, 3.03, 4.04, 5.05],
            ...
    ]
}

زبان کے ٹیسٹ کے اعداد و شمار:

ret_records = []interface{}{
    [6]interface{}{1500793319, 1.1, 2.2, 3.3, 4.4, 5.5}, 
    [6]interface{}{1500793259, 1.01, 2.02, 3.03, 4.04, 5.05}
}

FMZ کوانٹ پلیٹ فارمLogڈسپلےrecordsڈیٹا:

[
    {"Time":1500793319000,"Open":1.1,"High":2.2,"Low":3.3,"Close":4.4,"Volume":5.5},
    {"Time":1500793259000,"Open":1.01,"High":2.02,"Low":3.03,"Close":4.04,"Volume":5.05}
]

نوٹ: 1. دو جہتی صف میں پہلا عنصر کی قسم ہےintاور ایک ٹائم اسٹیمپ کی نمائندگی کرتا ہے۔ 2. ڈاکر خود بخود ٹائم اسٹیمپ کو 1000 سے ضرب دے گا ، جیسا کہ اوپر بتایا گیا ہے۔

    1. گٹ ڈپتھ: تبادلہ سے گہرائی کی معلومات (آرڈر بک ، ask1 ، ask2 ، bid1 ، bid2...) بازیافت کرتا ہے۔

کےmethodمیںrequestکی طرف سے بھیجا ڈاکر سننے کے جواب کی تقریب ہےdepth.

ڈاکر پیرامیٹر بھیجتا ہے:request.Params.symbol، جو حکمت عملی میں مقرر کرنسی کی بنیاد پر ڈوکر کی طرف سے بھیجا جاتا ہے.

ڈیٹا فارمیٹ درخواست جسم میں لے جایا جب ڈاکر اپنی مرضی کے مطابق پروٹوکول پلگ ان کی درخواست

{
    "access_key" : "access_key",
    "secret_key" : "secret_key",
    "nonce" :      "1500793319499",            // millisecond timestamp
    "method" :     "depth",
    "params" :     {"symbol" : "ETH_BTC"},     // Take the ETH_BTC trading pair for example
}

ڈوکر کو بھیجے گئے حتمی واپسی کی قیمت کا ڈھانچہ:

JSON ساخت

{
    "data" : {
        "time" : 1500793319499,
        "asks" : [ [1000, 0.5], [1001, 0.23], [1004, 2.1], ... ],
        "bids" : [ [999, 0.25], [998, 0.8], [995, 1.4], ... ],
    }
}
    1. گیٹ ٹریڈز: ایک مخصوص مدت کے اندر اندر پورے تبادلے کے تجارتی ریکارڈ حاصل کریں (کسی کی اپنی تجارت کو چھوڑ کر)

کےmethodمیںrequestڈاکر کی طرف سے سننے کے جواب کی تقریب کو بھیجا جاتا ہے:trades.

ڈوکر کی طرف سے بھیجے گئے پیرامیٹرز: کی قدرrequest.Params.symbolتجارت کی کرنسی ہے، مثال کے طور پر:btc، جو حکمت عملی کی ترتیبات کی بنیاد پر ڈوکر کی طرف سے بھیجا جاتا ہے.

اپنی مرضی کے مطابق پروٹوکول پلگ ان کی درخواست کرتے وقت ڈوکر کی طرف سے لے جانے والے ڈیٹا کی شکل مندرجہ ذیل ہے

{
    "access_key" : "access_key",
    "secret_key" : "secret_key",
    "nonce" :      "1500793319499",            // millisecond timestamp
    "method" :     "trades",
    "params" :     {"symbol" : "ETH_BTC"},     // Take the ETH_BTC trading pair for example
}

ڈوکر کو بھیجے گئے حتمی واپسی کی قیمت کا ڈھانچہ:

JSON ساخت

{ 
    "data": [
        {
            "id": 12232153,
            "time" : 1529919412968,
            "price": 1000,
            "amount": 0.5,
            "type": "buy",             // "buy"、"sell"
        },{
            "id": 12545664,
            "time" : 1529919412900,
            "price": 1001,
            "amount": 1,
            "type": "sell",
        },{
            ...
        }
    ]
}
    1. اکاؤنٹ حاصل کریں: اکاؤنٹ اثاثوں کی معلومات حاصل کریں.

کےmethodمیںrequestڈاکر کی طرف سے سننے کے جواب کی تقریب کو بھیجا جاتا ہے:accounts.

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

اپنی مرضی کے مطابق پروٹوکول پلگ ان کی درخواست کرتے وقت ڈوکر کی طرف سے لے جانے والے ڈیٹا کی شکل مندرجہ ذیل ہے

{
    "access_key" : "access_key",
    "secret_key" : "secret_key",
    "nonce" :      "1500793319499",            // millisecond timestamp
    "method" :     "accounts",
    "params" :     {},                         
}

ڈوکر کو بھیجے گئے حتمی واپسی کی قیمت کا ڈھانچہ:

JSON ساخت

{
    "data": [
        {"currency": "btc", "free": 1.2, "frozen": 0.1},
        {"currency": "ltc", "free": 25, "frozen": 2.1},
        {"currency": "ltc", "free": 25, "frozen": 2.1},
        ...
    ],
    "raw" : {...}             // It is possible to write the raw message (response) returned by the exchange when the plugin accesses the exchange
}
    1. خرید، فروخت: تجارت کے لئے آرڈر (مارکیٹ آرڈر یا حد آرڈر) رکھیں۔

کےmethodمیںrequestڈاکر کی طرف سے سننے کے جواب کی تقریب کو بھیجا جاتا ہے:trade.

ڈاکر کی طرف سے بھیجے گئے پیرامیٹرز:request.Params.type: یہ کال کر رہا ہے یا نہیں کی بنیاد پر ڈوکر کی طرف سے بھیجاexchange.Buyیاexchange.Sell, request.Params.price: کی پہلی پیرامیٹرAPIحکمت عملی میں بلایا فنکشن،request.Params.amount: کے دوسرے پیرامیٹرAPIحکمت عملی میں بلایا فنکشن،request.Params.symbol: مقررہ ٹریڈنگ کرنسی کی بنیاد پر ڈاکر کی طرف سے بھیجا.

اپنی مرضی کے مطابق پروٹوکول پلگ ان کی درخواست کرتے وقت ڈوکر کی طرف سے لے جانے والے ڈیٹا کی شکل مندرجہ ذیل ہے

{
    "access_key" : "access_key",
    "secret_key" : "secret_key",
    "nonce" :      "1500793319499",            // millisecond timestamp
    "method" :     "trade",
    "params" :     {
                       "symbol" : "ETH_BTC", 
                       "type" : "buy", 
                       "price" : "1000", 
                       "amount" : "1"
                   },                          // Example of an ETH_BTC trading pair, "type": "buy" buy request, price 1000, quantity 1
}

ڈوکر کو بھیجے گئے حتمی واپسی کی قیمت کا ڈھانچہ:

JSON ساخت

{
    "data": {
        "id": 125456,      // Order id returned after placing an order
                           // If the order id is in the form of a string like "asdf346sfasf532"
                           // Here the id can also be a string type
    }
}
    1. GetOrder: آرڈر آئی ڈی کی طرف سے ایک مخصوص آرڈر کی معلومات حاصل کریں

کےmethodمیںrequestڈاکر کی طرف سے سننے کے جواب کی تقریب کو بھیجا جاتا ہے:order.

ڈاکر کی طرف سے بھیجے گئے پیرامیٹرز:request.Params.id, request.Params.symbol.

اپنی مرضی کے مطابق پروٹوکول پلگ ان کی درخواست کرتے وقت ڈوکر کی طرف سے لے جانے والے ڈیٹا کی شکل مندرجہ ذیل ہے

{
    "access_key" : "access_key",
    "secret_key" : "secret_key",
    "nonce" :      "1500793319499",            // millisecond timestamp
    "method" :     "order",
    "params" :     {"symbol" : "ETH_BTC", "id" : "XXX"},     // Take the ETH_BTC trading pair and order ID XXX as an example. Please note that some exchanges use numerical order IDs, such as 123456, while others use string order IDs, such as poimd55sdfheqxv. The specific format of the order ID depends on the exchange.
}

ڈوکر کو بھیجے گئے حتمی واپسی کی قیمت کا ڈھانچہ:

JSON ساخت

{ 
    "data": {
        "id": 2565244,
        "amount": 0.15,
        "price": 1002,
        "status": "open",    // "open": pending, "closed": closed, "canceled": canceled
        "deal_amount": 0,
        "type": "buy",       // "buy"、"sell"
        "avg_price": 0,      // If not provided by the exchange, it can be assigned a value of 0 during processing
    }
}
    1. GetOrders: تمام خالی احکامات کے لئے معلومات حاصل کریں

کےmethodمیںrequestکی طرف سے بھیجا ڈاکر سننے کے جواب کی تقریب ہےorders.

ڈاکر کی طرف سے بھیجے گئے پیرامیٹرز:request.Params.symbol

اپنی مرضی کے مطابق پروٹوکول پلگ ان کی درخواست کرتے وقت ڈوکر کی طرف سے لے جانے والے ڈیٹا کی شکل مندرجہ ذیل ہے

{
    "access_key" : "access_key",
    "secret_key" : "secret_key",
    "nonce" :      "1500793319499",            // millisecond timestamp
    "method" :     "orders",
    "params" :     {"symbol" : "ETH_BTC"},     // Take the ETH_BTC trading pair for example
}

ڈوکر کو بھیجے گئے حتمی واپسی کی قیمت کا ڈھانچہ:

JSON ساخت

{
    "data": [{
        "id": 542156,
        "amount": 0.25,
        "price": 1005,
        "deal_amount": 0,
        "type": "buy",      // "buy"、"sell"
        "status": "open",   // "open"
    },{
        ...
    }]
}
    1. منسوخ آرڈر: مخصوص آرڈر آئی ڈی کے ساتھ آرڈر منسوخ کریں

کےmethodمیںrequestکی طرف سے بھیجا ڈاکر سننے کے جواب کی تقریب ہےcancel.

ڈاکر کی طرف سے بھیجے گئے پیرامیٹرز:request.Params.id(string type، API فنکشن کا پہلا پیرامیٹر جو حکمت عملی کے ذریعہ بلایا جاتا ہے)request.Params.symbol(مثال کے طور پر، بی ٹی سی، حکمت عملی کی طرف سے مقرر کرنسی کی بنیاد پر ڈوکر کی طرف سے بھیجا)

اپنی مرضی کے مطابق پروٹوکول پلگ ان کی درخواست کرتے وقت ڈوکر کی طرف سے لے جانے والے ڈیٹا کی شکل مندرجہ ذیل ہے

{
    "access_key" : "access_key",
    "secret_key" : "secret_key",
    "nonce" :      "1500793319499",            // millisecond timestamp
    "method" :     "cancel",
    "params" :     {"symbol" : "ETH_BTC", "id" : "XXX"},     // Take an ETH_BTC trading pair with an id of "XXX" (same as the GetOrder function's parameter id) for example
}

ڈوکر کو بھیجے گئے حتمی واپسی کی قیمت کا ڈھانچہ:

JSON ساخت

{
    "data": true,        // true or false
}
    1. آئی او:exchange.IOایف ایم زیڈ کوانٹ پلیٹ فارم کا فنکشن

کےmethodمیںrequestکی طرف سے بھیجا ڈوکر کی طرف سے سننے کے جواب کی تقریب کے ساتھ شروع ہوتا ہے_api_.

اپنی مرضی کے مطابق پروٹوکول پلگ ان کی درخواست کرتے وقت ڈوکر کی طرف سے لے جانے والے ڈیٹا کی شکل مندرجہ ذیل ہے

{
    "access_key" : "access_key",
    "secret_key" : "secret_key",
    "nonce" :      "1500793319499",            // millisecond timestamp
    "method" :     "__api_XXX",                // XXX is the API interface for the specific exchange (base address not included)
    "params" :     {"borrow_id" : "123", "symbol" : "cny"},      // Specifically, the parameters passed into the IO function
}

ڈوکر کو بھیجے گئے حتمی واپسی کی قیمت کا ڈھانچہ:

{
    "data": {...}       // The return value of a specific interface call
}

مثال کے طور پر، حکمت عملی کال:

var io_str = exchange.IO("api", "POST", "cancel_borrow", "symbol=cny&borrow_id=123")

پلگ ان میں ٹیسٹ کوڈ (گو زبان):

fmt.Println("request.Method:", request.Method, "request.Params:", request.Params)

پلگ ان کمانڈ لائن: 2017/08/31 10:19:59 دوڑ رہا ہےhttp://127.0.0.1:6666/DigitalAsset

پلگ ان کمانڈ لائن پرنٹ آؤٹ: request.Method, request.Paramsڈوکر کی طرف سے بھیجے گئے درخواست جسم میں، درخواست میں تجزیہ کردہ ڈیٹا مندرجہ ذیل ہے:request.Methodہے__api_cancel_borrow request.Paramsہے{"borrow_id" : "123", "symbol" : "cny"}

آپ ان کے ہینڈلنگ اپنی مرضی کے مطابق کر سکتے ہیںexchange.IOکالز جو براہ راست تبادلہ تک رسائی حاصلAPI.

# Attention:
# When calling exchange.IO("api", "POST", "/api/v1/getAccount", "symbol=BTC_USDT"), 
# If the second parameter is not POST but: exchange.IO("api", "GET", "/api/v1/getAccount", "symbol=BTC_USDT")
# is the GET method, which is then stored in the header Http-Method in the http request accepted by the custom protocol plugin.
# So you need to refer to the following sample code for the custom protocol handling IO function implementation:
// tapiCall function definition
func (p *iStocksExchange) tapiCall(method string, params map[string]string, httpType string) (js *Json, err error) {
    ...
}

// In the OnPost function
if strings.HasPrefix(request.Method, "__api_") {
    var js *Json
    js, err = e.tapiCall(request.Method[6:], request.Params, r.Header.Get("Http-Method"))
    ...
}
  • تبادلہ کے لئے حمایت.GetRawJSON:

بنیادی نظام خود کار طریقے سے کالز کو سنبھالتا ہےexchange.GetRawJSON، تو پلگ ان میں لاگو کرنے کی ضرورت نہیں ہے.

  • تبادلہ کے لئے حمایت.Go:

بنیادی نظام خود کار طریقے سے کالز کو سنبھالتا ہےexchange.Go، تو پلگ ان میں اسے ہینڈل کرنے کی ضرورت نہیں ہے.

var beginTime = new Date().getTime()
var ret = exchange.Go("GetDepth")
var endTime = new Date().getTime()
Log(endTime - beginTime, "#FF0000")

// Sleep(2000)
beginTime = new Date().getTime()
Log(exchange.GetTicker())
endTime = new Date().getTime()
Log(endTime - beginTime, "#FF0000")
var depth = ret.wait()
Log("depth:", depth)

img

img

# Note: If you specify a timeout when waiting using exchange. 
#      Always make sure to obtain the final data so that the concurrent threads of the application can be reclaimed.
  • مستقبل کے افعال کی حمایت:

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

جب مندرجہ ذیل افعال کو حکمت عملی میں بلایا جاتا ہے تو،Rpcدرخواست پلگ ان پروگرام کی طرف سے موصول دیگر انٹرفیس سے قدرے مختلف ہے. آپ کو کی شکل پر توجہ دینے کی ضرورت ہےRpcRequestاپنی مرضی کے مطابق پروٹوکول پلگ ان پروگرام میں۔ اہم فرق یہ ہے کہ پیرام کی قدر ایک مرکب ڈھانچہ ہے۔

سیٹContractType معاہدے کا کوڈ مقرر کریں.

{"access_key":"123","method":"io","nonce":1623307269528738000,"params":{"args":["quarter"],"code":2},"secret_key":"123"}

سیٹ ڈائریکشن مستقبل کے احکامات کی جگہ کے لئے سمت مقرر کرتا ہے.

{"access_key":"123","method":"io","nonce":1623308734966484000,"params":{"args":["closesell"],"code":1},"secret_key":"123"}

مارجن لیول سیٹ کریں فیوچر لیورج کا تعین کرتا ہے۔

{"access_key":"123","method":"io","nonce":1623308734966939000,"params":{"args":[12],"code":0},"secret_key":"123"}

پوزیشن حاصل کریں مستقبل کی پوزیشن حاصل کریں. کبexchange.GetPosition()کہا جاتا ہے:

{"access_key":"123","method":"io","nonce":1623308734967442000,"params":{"args":[],"code":3},"secret_key":"123"}

کبexchange.GetPosition("swap")کہا جاتا ہے:

{"access_key":"123","method":"io","nonce":1623308734967442000,"params":{"args":["swap"],"code":3},"secret_key":"123"}
  • مکمل گو زبان اپنی مرضی کے مطابق پروٹوکول پلگ ان کی مثال (بیٹگو ایکسچینج تک رسائی)
/*
GOOS=linux GOARCH=amd64 go build -ldflags '-s -w -extldflags -static' rest_bitgo.go
*/
package main

import (
    "bytes"
    "crypto/md5"
    "encoding/hex"
    "encoding/json"
    "errors"
    "flag"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "net/url"
    "sort"
    "strconv"
    "strings"
    "time"
)

func toFloat(s interface{}) float64 {
    var ret float64
    switch v := s.(type) {
    case float64:
        ret = v
    case float32:
        ret = float64(v)
    case int64:
        ret = float64(v)
    case int:
        ret = float64(v)
    case int32:
        ret = float64(v)
    case string:
        ret, _ = strconv.ParseFloat(strings.TrimSpace(v), 64)
    }
    return ret
}

func float2str(i float64) string {
    return strconv.FormatFloat(i, 'f', -1, 64)
}

func toInt64(s interface{}) int64 {
    var ret int64
    switch v := s.(type) {
    case int:
        ret = int64(v)
    case float64:
        ret = int64(v)
    case bool:
        if v {
            ret = 1
        } else {
            ret = 0
        }
    case int64:
        ret = v
    case string:
        ret, _ = strconv.ParseInt(strings.TrimSpace(v), 10, 64)
    }
    return ret
}

func toString(s interface{}) string {
    var ret string
    switch v := s.(type) {
    case string:
        ret = v
    case int64:
        ret = strconv.FormatInt(v, 10)
    case float64:
        ret = strconv.FormatFloat(v, 'f', -1, 64)
    case bool:
        ret = strconv.FormatBool(v)
    default:
        ret = fmt.Sprintf("%v", s)
    }
    return ret
}

type Json struct {
    data interface{}
}

func NewJson(body []byte) (*Json, error) {
    j := new(Json)
    err := j.UnmarshalJSON(body)
    if err != nil {
        return nil, err
    }
    return j, nil
}

func (j *Json) UnmarshalJSON(p []byte) error {
    return json.Unmarshal(p, &j.data)
}

func (j *Json) Get(key string) *Json {
    m, err := j.Map()
    if err == nil {
        if val, ok := m[key]; ok {
            return &Json{val}
        }
    }
    return &Json{nil}
}

func (j *Json) CheckGet(key string) (*Json, bool) {
    m, err := j.Map()
    if err == nil {
        if val, ok := m[key]; ok {
            return &Json{val}, true
        }
    }
    return nil, false
}

func (j *Json) Map() (map[string]interface{}, error) {
    if m, ok := (j.data).(map[string]interface{}); ok {
        return m, nil
    }
    return nil, errors.New("type assertion to map[string]interface{} failed")
}

func (j *Json) Array() ([]interface{}, error) {
    if a, ok := (j.data).([]interface{}); ok {
        return a, nil
    }
    return nil, errors.New("type assertion to []interface{} failed")
}

func (j *Json) Bool() (bool, error) {
    if s, ok := (j.data).(bool); ok {
        return s, nil
    }
    return false, errors.New("type assertion to bool failed")
}

func (j *Json) String() (string, error) {
    if s, ok := (j.data).(string); ok {
        return s, nil
    }
    return "", errors.New("type assertion to string failed")
}

func (j *Json) Bytes() ([]byte, error) {
    if s, ok := (j.data).(string); ok {
        return []byte(s), nil
    }
    return nil, errors.New("type assertion to []byte failed")
}

func (j *Json) Int() (int, error) {
    if f, ok := (j.data).(float64); ok {
        return int(f), nil
    }

    return -1, errors.New("type assertion to float64 failed")
}

func (j *Json) MustArray(args ...[]interface{}) []interface{} {
    var def []interface{}

    switch len(args) {
    case 0:
    case 1:
        def = args[0]
    default:
        log.Panicf("MustArray() received too many arguments %d", len(args))
    }

    a, err := j.Array()
    if err == nil {
        return a
    }

    return def
}

func (j *Json) MustMap(args ...map[string]interface{}) map[string]interface{} {
    var def map[string]interface{}

    switch len(args) {
    case 0:
    case 1:
        def = args[0]
    default:
        log.Panicf("MustMap() received too many arguments %d", len(args))
    }

    a, err := j.Map()
    if err == nil {
        return a
    }

    return def
}

func (j *Json) MustString(args ...string) string {
    var def string

    switch len(args) {
    case 0:
    case 1:
        def = args[0]
    default:
        log.Panicf("MustString() received too many arguments %d", len(args))
    }

    s, err := j.String()
    if err == nil {
        return s
    }

    return def
}

func (j *Json) MustInt64() int64 {
    var ret int64
    var err error
    switch v := j.data.(type) {
    case int:
        ret = int64(v)
    case int64:
        ret = v
    case float64:
        ret = int64(v)
    case string:
        if ret, err = strconv.ParseInt(v, 10, 64); err != nil {
            panic(err)
        }
    default:
        ret = 0
        //panic("type assertion to int64 failed")
    }
    return ret
}

func (j *Json) MustFloat64() float64 {
    var ret float64
    var err error
    switch v := j.data.(type) {
    case int:
        ret = float64(v)
    case int64:
        ret = float64(v)
    case float64:
        ret = v
    case string:
        v = strings.Replace(v, ",", "", -1)
        if ret, err = strconv.ParseFloat(v, 64); err != nil {
            panic(err)
        }
    default:
        ret = 0
        //panic("type assertion to float64 failed")
    }
    return ret
}

type iBitgo struct {
    accessKey     string
    secretKey     string
    currency      string
    opCurrency    string
    baseCurrency  string
    secret        string
    secretExpires int64
    apiBase       string
    step          int64
    newRate       float64
    timeout       time.Duration
    timeLocation  *time.Location
}

type MapSorter []Item

type Item struct {
    Key string
    Val string
}

func NewMapSorter(m map[string]string) MapSorter {
    ms := make(MapSorter, 0, len(m))

    for k, v := range m {
        if strings.HasPrefix(k, "!") {
            k = strings.Replace(k, "!", "", -1)
        }
        ms = append(ms, Item{k, v})
    }

    return ms
}

func (ms MapSorter) Len() int {
    return len(ms)
}

func (ms MapSorter) Less(i, j int) bool {
    //return ms[i].Val < ms[j].Val // Sort by value
    return ms[i].Key < ms[j].Key // Sort by key
}

func (ms MapSorter) Swap(i, j int) {
    ms[i], ms[j] = ms[j], ms[i]
}

func encodeParams(params map[string]string, escape bool) string {
    ms := NewMapSorter(params)
    sort.Sort(ms)

    v := url.Values{}
    for _, item := range ms {
        v.Add(item.Key, item.Val)
    }
    if escape {
        return v.Encode()
    }
    var buf bytes.Buffer
    keys := make([]string, 0, len(v))
    for k := range v {
        keys = append(keys, k)
    }
    sort.Strings(keys)
    for _, k := range keys {
        vs := v[k]
        prefix := k + "="
        for _, v := range vs {
            if buf.Len() > 0 {
                buf.WriteByte('&')
            }
            buf.WriteString(prefix)
            buf.WriteString(v)
        }
    }
    return buf.String()
}

func newBitgo(accessKey, secretKey string) *iBitgo {
    s := new(iBitgo)
    s.accessKey = accessKey
    s.secretKey = secretKey
    s.apiBase = "https://www.bitgo.cn"
    s.timeout = 20 * time.Second
    s.timeLocation = time.FixedZone("Asia/Shanghai", 8*60*60)

    return s
}

func (p *iBitgo) apiCall(method string) (*Json, error) {
    req, err := http.NewRequest("POST", fmt.Sprintf("%s/appApi.html?%s", p.apiBase, method), nil)
    if err != nil {
        return nil, err
    }
    req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    b, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }
    return NewJson(b)
}

func (p *iBitgo) GetTicker(symbol string) (ticker interface{}, err error) {
    var js *Json
    js, err = p.apiCall("action=market&symbol=" + symbol)
    if err != nil {
        return
    }
    dic := js.Get("data")
    ticker = map[string]interface{}{
        "time": js.Get("time").MustInt64(),
        "buy":  dic.Get("buy").MustFloat64(),
        "sell": dic.Get("sell").MustFloat64(),
        "last": dic.Get("last").MustFloat64(),
        "high": dic.Get("high").MustFloat64(),
        "low":  dic.Get("low").MustFloat64(),
        "vol":  dic.Get("vol").MustFloat64(),
    }
    return
}

func (p *iBitgo) GetDepth(symbol string) (depth interface{}, err error) {
    var js *Json
    js, err = p.apiCall("action=depth&symbol=" + symbol)
    if err != nil {
        return
    }
    dic := js.Get("data")

    asks := [][2]float64{}
    bids := [][2]float64{}

    for _, pair := range dic.Get("asks").MustArray() {
        arr := pair.([]interface{})
        asks = append(asks, [2]float64{toFloat(arr[0]), toFloat(arr[1])})
    }

    for _, pair := range dic.Get("bids").MustArray() {
        arr := pair.([]interface{})
        bids = append(bids, [2]float64{toFloat(arr[0]), toFloat(arr[1])})
    }
    depth = map[string]interface{}{
        "time": js.Get("time").MustInt64(),
        "asks": asks,
        "bids": bids,
    }
    return
}

func (p *iBitgo) GetTrades(symbol string) (trades interface{}, err error) {
    var js *Json
    js, err = p.apiCall("action=trades&symbol=" + symbol)
    if err != nil {
        return
    }
    dic := js.Get("data")
    items := []map[string]interface{}{}
    for _, pair := range dic.MustArray() {
        item := map[string]interface{}{}
        arr := pair.(map[string]interface{})
        item["id"] = toInt64(arr["id"])
        item["price"] = toFloat(arr["price"])
        item["amount"] = toFloat(arr["amount"])
        // trade.Time = toInt64(arr["time"]) * 1000
        if toString(arr["en_type"]) == "bid" {
            item["type"] = "buy"
        } else {
            item["type"] = "sell"
        }
        items = append(items, item)
    }
    trades = items
    return
}

func (p *iBitgo) GetRecords(step int64, symbol string) (records interface{}, err error) {
    var js *Json
    js, err = p.apiCall(fmt.Sprintf("action=kline&symbol=%s&step=%d", symbol, step*60))
    if err != nil {
        return
    }
    items := []interface{}{}
    for _, pair := range js.Get("data").MustArray() {
        arr := pair.([]interface{})
        if len(arr) < 6 {
            err = errors.New("response format error")
            return
        }
        item := [6]interface{}{}
        item[0] = toInt64(arr[0])
        item[1] = toFloat(arr[1])
        item[2] = toFloat(arr[2])
        item[3] = toFloat(arr[3])
        item[4] = toFloat(arr[4])
        item[5] = toFloat(arr[5])

        items = append(items, item)
    }
    records = items
    return
}

func (p *iBitgo) tapiCall(method string, params map[string]string) (js *Json, err error) {
    if params == nil {
        params = map[string]string{}
    }
    params["api_key"] = p.accessKey
    h := md5.New()
    h.Write([]byte(encodeParams(params, false) + "&secret_key=" + p.secretKey))
    params["sign"] = strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
    params["action"] = method
    qs := encodeParams(params, false)

    req, err := http.NewRequest("POST", fmt.Sprintf("%s/appApi.html?%s", p.apiBase, qs), nil)
    if err != nil {
        return nil, err
    }
    req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    b, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }
    js, err = NewJson(b)
    if js != nil {
        if code := js.Get("code").MustInt64(); code != 200 {
            s := js.Get("msg").MustString()
            if s == "" {
                s = fmt.Sprintf("%v", toString(js.data))
            }
            return nil, errors.New(s)
        }
    }
    return js, err
}

func (p *iBitgo) GetAccount(symbol string) (account interface{}, err error) {
    var js *Json
    js, err = p.tapiCall("userinfo", nil)
    if err != nil {
        return
    }
    mp := js.Get("data")
    assets := map[string]map[string]interface{}{}
    for k := range mp.MustMap() {
        dic := mp.Get(k)
        if k == "free" {
            for c := range dic.MustMap() {
                if _, ok := assets[c]; !ok {
                    assets[c] = map[string]interface{}{}
                }
                assets[c]["currency"] = c
                assets[c]["free"] = dic.Get(c).MustFloat64()
            }
        } else if k == "frozen" {
            for c := range dic.MustMap() {
                if _, ok := assets[c]; !ok {
                    assets[c] = map[string]interface{}{}
                }
                assets[c]["currency"] = c
                assets[c]["frozen"] = dic.Get(c).MustFloat64()
            }
        }
    }
    accounts := []map[string]interface{}{}
    for _, pair := range assets {
        accounts = append(accounts, pair)
    }

    account = accounts
    return
}

func (p *iBitgo) Trade(side string, price, amount float64, symbol string) (orderId interface{}, err error) {
    var js *Json
    js, err = p.tapiCall("trade", map[string]string{
        "symbol": symbol,
        "type":   side,
        "price":  float2str(price),
        "amount": float2str(amount),
    })
    if err != nil {
        return
    }
    orderId = map[string]int64{"id": js.Get("orderId").MustInt64()}
    return
}

func (p *iBitgo) GetOrders(symbol string) (orders interface{}, err error) {
    var js *Json
    js, err = p.tapiCall("entrust", map[string]string{"symbol": symbol})
    if err != nil {
        return
    }
    items := []map[string]interface{}{}
    for _, ele := range js.Get("data").MustArray() {
        mp := ele.(map[string]interface{})
        item := map[string]interface{}{}
        item["id"] = toInt64(mp["id"])
        item["amount"] = toFloat(mp["count"])
        if _, ok := mp["prize"]; ok {
            item["price"] = toFloat(mp["prize"])
        } else {
            item["price"] = toFloat(mp["price"])
        }
        item["deal_amount"] = toFloat(mp["success_count"])

        if toInt64(mp["type"]) == 0 {
            item["type"] = "buy"
        } else {
            item["type"] = "sell"
        }
        item["status"] = "open"
        items = append(items, item)
    }
    return items, nil
}

func (p *iBitgo) GetOrder(orderId int64, symbol string) (order interface{}, err error) {
    var js *Json
    js, err = p.tapiCall("order", map[string]string{"id": toString(orderId)})
    if err != nil {
        return
    }

    found := false
    item := map[string]interface{}{}
    for _, ele := range js.Get("data").MustArray() {
        mp := ele.(map[string]interface{})
        if toInt64(mp["id"]) != orderId {
            continue
        }
        item["id"] = toInt64(mp["id"])
        item["amount"] = toFloat(mp["count"])
        if _, ok := mp["prize"]; ok {
            item["price"] = toFloat(mp["prize"])
        } else {
            item["price"] = toFloat(mp["price"])
        }
        item["deal_amount"] = toFloat(mp["success_count"])

        if toInt64(mp["type"]) == 0 {
            item["type"] = "buy"
        } else {
            item["type"] = "sell"
        }
        switch toInt64(mp["status"]) {
        case 1, 2:
            item["status"] = "open"
        case 3:
            item["status"] = "closed"
        case 4:
            item["status"] = "cancelled"
        }
        found = true
        break
    }
    if !found {
        return nil, errors.New("order not found")
    }
    return item, nil
}

func (p *iBitgo) CancelOrder(orderId int64, symbol string) (ret bool, err error) {
    _, err = p.tapiCall("cancel_entrust", map[string]string{"id": strconv.FormatInt(orderId, 10)})
    if err != nil {
        return
    }
    ret = true
    return
}

type RpcRequest struct {        // The fields in a struct must start with an uppercase letter, otherwise they cannot be parsed correctly. Structs can have exported and unexported fields, where fields starting with an uppercase letter are considered exported.
                                // During unmarshaling, the JSON tag of a struct is used to match and find the corresponding field. Therefore, modifiers are required in this case.
    AccessKey string            `json:"access_key"`
    SecretKey string            `json:"secret_key"`
    Nonce     int64             `json:"nonce"`
    Method    string            `json:"method"`
    Params    map[string]string `json:"params"`
}

func OnPost(w http.ResponseWriter, r *http.Request) {
    var ret interface{}
    defer func() {
        if e := recover(); e != nil {
            if ee, ok := e.(error); ok {
                e = ee.Error()
            }
            ret = map[string]string{"error": fmt.Sprintf("%v", e)}
        }
        b, _ := json.Marshal(ret)
        w.Write(b)
    }()

    b, err := ioutil.ReadAll(r.Body)
    if err != nil {
        panic(err)
    }
    var request RpcRequest
    err = json.Unmarshal(b, &request)
    if err != nil {
        panic(err)
    }
    e := newBitgo(request.AccessKey, request.SecretKey)
    symbol := request.Params["symbol"]
    if s := request.Params["access_key"]; len(s) > 0 {
        e.accessKey = s
    }
    if s := request.Params["secret_key"]; len(s) > 0 {
        e.secretKey = s
    }
    if symbolIdx, ok := map[string]int{
        "btc":  1,
        "ltc":  2,
        "etp":  3,
        "eth":  4,
        "etc":  5,
        "doge": 6,
        "bec":  7,
    }[strings.Replace(strings.ToLower(symbol), "_cny", "", -1)]; ok {
        symbol = toString(symbolIdx)
    }
    var data interface{}
    switch request.Method {
    case "ticker":
        data, err = e.GetTicker(symbol)
    case "depth":
        data, err = e.GetDepth(symbol)
    case "trades":
        data, err = e.GetTrades(symbol)
    case "records":
        data, err = e.GetRecords(toInt64(request.Params["period"]), symbol)
    case "accounts":
        data, err = e.GetAccount(symbol)
    case "trade":
        side := request.Params["type"]
        if side == "buy" {
            side = "0"
        } else {
            side = "1"
        }
        price := toFloat(request.Params["price"])
        amount := toFloat(request.Params["amount"])
        data, err = e.Trade(side, price, amount, symbol)
    case "orders":
        data, err = e.GetOrders(symbol)
    case "order":
        data, err = e.GetOrder(toInt64(request.Params["id"]), symbol)
    case "cancel":
        data, err = e.CancelOrder(toInt64(request.Params["id"]), symbol)
    default:
        if strings.HasPrefix(request.Method, "__api_") {
            data, err = e.tapiCall(request.Method[6:], request.Params)
        } else {
            panic(errors.New(request.Method + " not support"))
        }
    }
    if err != nil {
        panic(err)
    }
    ret = map[string]interface{}{
        "data": data,
    }

    return
}

func main() {
    var addr = flag.String("b", "127.0.0.1:6666", "bind addr")
    flag.Parse()
    if *addr == "" {
        flag.Usage()
        return
    }
    basePath := "/exchange"
    log.Println("Running ", fmt.Sprintf("http://%s%s", *addr, basePath), "...")
    http.HandleFunc(basePath, OnPost)
    http.ListenAndServe(*addr, nil)
}

مزید