3
پر توجہ دیں
1444
پیروکار

ڈیجیٹل کرنسی پیئر ٹریڈنگ حکمت عملی کے سورس کوڈ اور FMZ پلیٹ فارم کے تازہ ترین API کا تعارف

میں تخلیق کیا: 2024-07-10 16:36:54, تازہ کاری: 2024-07-12 15:53:41
comments   5
hits   2914

ڈیجیٹل کرنسی پیئر ٹریڈنگ حکمت عملی کے سورس کوڈ اور FMZ پلیٹ فارم کے تازہ ترین API کا تعارف

دیباچہ

پچھلے مضمون میں جوڑے کی تجارت کے اصول اور بیک ٹیسٹنگ، https://www.fmz.com/digest-topic/10457 کو متعارف کرایا گیا تھا۔ FMZ پلیٹ فارم پر مبنی عملی سورس کوڈ یہ ہے حکمت عملی نسبتاً آسان اور واضح ہے، جو سیکھنے کے لیے موزوں ہے۔ FMZ پلیٹ فارم نے حال ہی میں اپنے کچھ APIs کو ملٹی ٹریڈنگ جوڑی کی حکمت عملیوں کے لیے زیادہ دوستانہ بنانے کے لیے اپ گریڈ کیا ہے۔ یہ مضمون اس حکمت عملی کے جاوا اسکرپٹ سورس کوڈ کو تفصیل سے متعارف کرائے گا۔ اگرچہ حکمت عملی صرف ایک سو سطروں پر مشتمل ہے، لیکن اس میں ایک مکمل حکمت عملی کے لیے درکار تمام پہلو موجود ہیں۔ مخصوص APIs کے لیے، براہ کرم API دستاویزات سے رجوع کریں، جس کا تفصیل سے بیان کیا گیا ہے۔ حکمت عملی کا عوامی پتہ: https://www.fmz.com/strategy/456143 براہ راست کاپی کیا جا سکتا ہے۔

FMZ پلیٹ فارم کا استعمال

اگر آپ FMZ پلیٹ فارم سے واقف نہیں ہیں، تو میں آپ کو اس ٹیوٹوریل کو پڑھنے کی سختی سے مشورہ دیتا ہوں: https://www.fmz.com/bbs-topic/4145۔ یہ پلیٹ فارم کے بنیادی افعال اور شروع سے روبوٹ کو تعینات کرنے کا طریقہ متعارف کراتا ہے۔

پالیسی فریم ورک

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

function main(){
    while(true){
        //策略内容
        Sleep(Interval * 1000) //Sleep
    }
}

تاریخی ڈیٹا ریکارڈ کریں۔

روبوٹ مختلف وجوہات کی بناء پر بار بار دوبارہ شروع ہو گا، جیسے کہ خرابیاں، پیرامیٹر اپ ڈیٹس، حکمت عملی اپ ڈیٹس وغیرہ، اور کچھ ڈیٹا کو اگلے سٹارٹ اپ پر استعمال کے لیے محفوظ کرنے کی ضرورت ہے۔ ریٹرن کا حساب لگانے میں استعمال کے لیے ابتدائی ایکویٹی کو کیسے بچانا ہے اس کا ایک مظاہرہ یہاں ہے۔_G() فنکشن مختلف ڈیٹا کو محفوظ کر سکتا ہے۔_G(key, value) قدر کی قدر کو ذخیرہ کر سکتا ہے اور اسے _G(key) کے ساتھ کال کر سکتا ہے، جہاں کلید ایک تار ہے۔

let init_eq = 0 //定义初始权益
if(!_G('init_eq')){  //如果没有储存_G('init_eq')返回null
    init_eq = total_eq
    _G('init_eq', total_eq) //由于没有储存,初始权益为当前权益,并在这里储存
}else{
    init_eq = _G('init_eq') //如果储存,读取初始权益的值
}

حکمت عملی غلطی رواداری

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

let pos = _C(exchange.GetPosition, pair)

let ticker_A = exchange.GetTicker(pair_a)
let ticker_B = exchange.GetTicker(pair_b)
if(!ticker_A || !ticker_B){
    continue //如果数据不可用,就跳出这次循环
}

ملٹی کرنسی کے موافق API

GetPosition، GetTicker، اور GetRecords جیسے فنکشنز ایکسچینج باؤنڈ ٹریڈنگ پیئر سیٹ کیے بغیر متعلقہ ڈیٹا حاصل کرنے کے لیے ٹریڈنگ پیئر پیرامیٹر کا اضافہ کر سکتے ہیں، جو متعدد تجارتی جوڑی کی حکمت عملیوں کی مطابقت کو بہت زیادہ سہولت فراہم کرتا ہے۔ اپ گریڈ کی تفصیلی معلومات کے لیے، براہ کرم مضمون سے رجوع کریں: https://www.fmz.com/digest-topic/10451۔ بلاشبہ، آپ کو اس کی حمایت کے لیے جدید ترین ہوسٹنگ کی ضرورت ہے، اگر آپ کی ہوسٹنگ بہت پرانی ہے، تو آپ کو اپ گریڈ کرنے کی ضرورت ہے۔

حکمت عملی کے پیرامیٹرز

  • Pair_A ٹریڈنگ کرنسی A: ٹریڈنگ پیئر A جس کو ٹریڈنگ کے لیے جوڑا جانا ضروری ہے آپ کو خود ہی ٹریڈنگ جوڑی کا انتخاب کرنا ہوگا جو آپ پچھلے آرٹیکل میں دیے گئے تعارف اور بیک ٹیسٹنگ کا حوالہ دے سکتے ہیں۔
  • Pair_B تجارتی کرنسی B: تجارتی جوڑا B جسے جوڑا بنانے کی ضرورت ہے۔
  • کوٹ بیس کرنسی: فیوچر ایکسچینج کی مارجن کرنسی، عام طور پر USDT
  • پی سی ٹی گرڈ سائز: پوزیشنز کو شامل کرنے میں کتنا انحراف ہے، تفصیلات کے لیے حکمت عملی کے اصولوں پر مضمون دیکھیں، فیس اور پھسل جانے کی وجہ سے، یہ بہت چھوٹا نہیں ہونا چاہیے۔
  • Trade_Value: گرڈ سائز سے ہر انحراف کے لیے ایک پوزیشن شامل کرنے کی لین دین کی قیمت۔
  • Ice_Value: اگر لین دین کی قدر بہت زیادہ ہے، تو آپ کسی پوزیشن کو کھولنے کے لیے آئس برگ ویلیو کا استعمال کر سکتے ہیں، اسے لین دین کی قدر کے برابر سیٹ کیا جا سکتا ہے۔
  • Max_Value زیادہ سے زیادہ ہولڈنگز: ایک ہی کرنسی کی زیادہ سے زیادہ ہولڈنگز، بہت زیادہ عہدوں پر فائز ہونے کے خطرے سے بچنے کے لیے
  • N اوسط قیمت کا پیرامیٹر: اوسط قیمت کے تناسب کو شمار کرنے کے لیے استعمال ہونے والا پیرامیٹر، یونٹ گھنٹہ ہے، جیسے کہ 100 100 گھنٹے کی اوسط کو ظاہر کرتا ہے۔
  • وقفہ نیند کا وقت (سیکنڈ): حکمت عملی کے ہر چکر کے درمیان نیند کا وقت

مکمل پالیسی نوٹس

اگر آپ اب بھی نہیں سمجھتے ہیں، تو آپ اپنے سوالات کو حل کرنے کے لیے FMZ کے API دستاویزات، ڈیبگنگ ٹولز، اور مارکیٹ میں عام طور پر استعمال ہونے والے AI ڈائیلاگ ٹولز کا استعمال کر سکتے ہیں۔

function GetPosition(pair){
    let pos = _C(exchange.GetPosition, pair)
    if(pos.length == 0){ //返回为空代表没有持仓
        return {amount:0, price:0, profit:0}
    }else if(pos.length > 1){ //策略要设置为单向持仓模式
        throw '不支持双向持仓'
    }else{ //为了方便,多仓持仓量为正,空仓持仓量为负
        return {amount:pos[0].Type == 0 ? pos[0].Amount : -pos[0].Amount, price:pos[0].Price, profit:pos[0].Profit}
    }
}

function GetRatio(){
    let kline_A = exchange.GetRecords(Pair_A+"_"+Quote+".swap", 60*60, N) //小时K线
    let kline_B = exchange.GetRecords(Pair_B+"_"+Quote+".swap", 60*60, N)
    let total = 0
    for(let i= Math.min(kline_A.length,kline_B.length)-1; i >= 0; i--){ //反过来计算,避免K线长度不够
        total += kline_A[i].Close / kline_B[i].Close
    }
    return total / Math.min(kline_A.length,kline_B.length)
}

function GetAccount(){
    let account = _C(exchange.GetAccount)
    let total_eq = 0
    if(exchange.GetName == 'Futures_OKCoin'){ //由于这里的API并不兼容,目前仅OKX期货交易所获取到总权益
        total_eq = account.Info.data[0].totalEq //其他交易所的宗权益Info中也包含,可以自己对着交易所API文档找找
    }else{
        total_eq = account.Balance //其它交易所暂时使用可用余额,会造成计算收益错误,但不影响策略使用
    }
    let init_eq = 0
    if(!_G('init_eq')){
        init_eq = total_eq
        _G('init_eq', total_eq)
    }else{
        init_eq = _G('init_eq')
    }
    LogProfit(total_eq - init_eq)
    return total_eq
}

function main(){
    var precision = exchange.GetMarkets() //这里获取精度
    var last_get_ratio_time = Date.now()
    var ratio = GetRatio()
    var total_eq = GetAccount()
    while(true){
        let start_loop_time = Date.now()
        if(Date.now() - last_get_ratio_time > 10*60*1000){ //每10分钟更新下均价和账户信息
            ratio = GetRatio()
            total_eq = GetAccount()
            last_get_ratio_time = Date.now()
        }
        let pair_a = Pair_A+"_"+Quote+".swap" //交易对的设置形如BTC_USDT.swap
        let pair_b = Pair_B+"_"+Quote+".swap"
        let CtVal_a = "CtVal" in precision[pair_a] ? precision[pair_a].CtVal : 1 //有的交易所用张来代表数量,如一张代表0.01个币,因此需要换算下
        let CtVal_b = "CtVal" in precision[pair_b] ? precision[pair_b].CtVal : 1 //不含这个字段的不用张
        let position_A = GetPosition(pair_a)
        let position_B = GetPosition(pair_b)
        let ticker_A = exchange.GetTicker(pair_a)
        let ticker_B = exchange.GetTicker(pair_b)
        if(!ticker_A || !ticker_B){ //如果返回数据异常,跳出这次循环
            continue
        }
        let diff = (ticker_A.Last / ticker_B.Last - ratio) / ratio //计算偏离的比例
        let aim_value = - Trade_Value * diff / Pct //目标持有的仓位
        let id_A = null
        let id_B = null
        //以下是具体的开仓逻辑
        if( -aim_value + position_A.amount*CtVal_a*ticker_A.Last > Trade_Value && position_A.amount*CtVal_a*ticker_A.Last > -Max_Value){
            id_A = exchange.CreateOrder(pair_a, "sell", ticker_A.Buy, _N(Ice_Value / (ticker_A.Buy * CtVal_a), precision[pair_a].AmountPrecision))
        }
        if( -aim_value - position_B.amount*CtVal_b*ticker_B.Last > Trade_Value && position_B.amount*CtVal_b*ticker_B.Last < Max_Value){
            id_B = exchange.CreateOrder(pair_b, "buy", ticker_B.Sell, _N(Ice_Value / (ticker_B.Sell * CtVal_b), precision[pair_b].AmountPrecision))
        }
        if( aim_value - position_A.amount*CtVal_a*ticker_A.Last > Trade_Value && position_A.amount*CtVal_a*ticker_A.Last < Max_Value){
            id_A = exchange.CreateOrder(pair_a, "buy", ticker_A.Sell, _N(Ice_Value / (ticker_A.Sell * CtVal_a), precision[pair_a].AmountPrecision))
        }
        if( aim_value + position_B.amount*CtVal_b*ticker_B.Last > Trade_Value &&  position_B.amount*CtVal_b*ticker_B.Last > -Max_Value){
            id_B = exchange.CreateOrder(pair_b, "sell", ticker_B.Buy, _N(Ice_Value / (ticker_B.Buy * CtVal_b), precision[pair_b].AmountPrecision))
        }
        if(id_A){
            exchange.CancelOrder(id_A) //这里直接撤销
        }
        if(id_B){
            exchange.CancelOrder(id_B)
        }
        let table = {
            type: "table",
            title: "交易信息",
            cols: ["初始权益", "当前权益", Pair_A+"仓位", Pair_B+"仓位", Pair_A+"持仓价", Pair_B+"持仓价", Pair_A+"收益", Pair_B+"收益", Pair_A+"价格", Pair_B+"价格", "当前比价", "平均比价", "偏离均价", "循环延时"],
            rows: [[_N(_G('init_eq'),2), _N(total_eq,2), _N(position_A.amount*CtVal_a*ticker_A.Last, 1), _N(position_B.amount*CtVal_b*ticker_B.Last,1),
                _N(position_A.price, precision[pair_a].PircePrecision), _N(position_B.price, precision[pair_b].PircePrecision),
                _N(position_A.profit, 1), _N(position_B.profit, 1), ticker_A.Last, ticker_B.Last,
                _N(ticker_A.Last / ticker_B.Last,6), _N(ratio, 6), _N(diff, 4), (Date.now() - start_loop_time)+"ms"
            ]]
        }
        LogStatus("`" + JSON.stringify(table) + "`") //这个函数会在机器人页面显示包含以上信息的表格
        Sleep(Interval * 1000) //休眠时间为ms
    }
}