avatar of 发明者量化-小小梦 发明者量化-小小梦
پر توجہ دیں نجی پیغام
4
پر توجہ دیں
1271
پیروکار

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

میں تخلیق کیا: 2021-07-02 14:35:34, تازہ کاری: 2023-09-21 21:09:56
comments   22
hits   6170

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

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

حال ہی میں، FMZ آفیشل گروپ میں Martingale کی حکمت عملیوں پر بہت سی بات چیت ہوئی ہے، لیکن پلیٹ فارم پر ڈیجیٹل کرنسی کے معاہدوں کے لیے Martingale کی بہت سی حکمت عملییں موجود نہیں ہیں۔ اس لیے، میں نے کرپٹو کرنسی فیوچرز کے لیے ایک سادہ مارٹنگیل حکمت عملی وضع کرنے کا موقع لیا۔ اسے مارٹن جیسی حکمت عملی کیوں کہا جاتا ہے کیونکہ مارٹن حکمت عملی کے ممکنہ خطرات واقعی چھوٹے نہیں ہیں، اس لیے اسے مکمل طور پر مارٹن کی حکمت عملی کے مطابق نہیں بنایا گیا ہے۔ تاہم، اس قسم کی حکمت عملی میں اب بھی کافی خطرات ہیں، اور Martingale حکمت عملی کے پیرامیٹر کی ترتیبات کا خطرات سے گہرا تعلق ہے، اور خطرات کو نظر انداز نہیں کیا جانا چاہیے۔

یہ مضمون بنیادی طور پر مارٹن قسم کی حکمت عملیوں کی وضاحت کرتا ہے اور اس سے سیکھتا ہے۔

کل ایکویٹی حاصل کریں۔

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

لہذا، ہم مختلف تبادلے کے مطابق اس ڈیٹا کو حاصل کرنے کے لیے فنکشنز ڈیزائن کرتے ہیں:

// OKEX V5 获取总权益
function getTotalEquity_OKEX_V5() {
    var totalEquity = null 
    var ret = exchange.IO("api", "GET", "/api/v5/account/balance", "ccy=USDT")
    if (ret) {
        try {
            totalEquity = parseFloat(ret.data[0].details[0].eq)
        } catch(e) {
            Log("获取账户总权益失败!")
            return null
        }
    }
    return totalEquity
}

// 币安期货
function getTotalEquity_Binance() {
    var totalEquity = null 
    var ret = exchange.GetAccount()
    if (ret) {
        try {
            totalEquity = parseFloat(ret.Info.totalWalletBalance)
        } catch(e) {
            Log("获取账户总权益失败!")
            return null
        }
    }
    return totalEquity
}

کوڈ میںtotalEquityیہ کل ایکویٹی ہے جس کی ہمیں ضرورت ہے۔ پھر ہم کالنگ انٹری کے طور پر ایک فنکشن لکھتے ہیں اور ایکسچینج کے نام کے مطابق متعلقہ فنکشن کو کال کرتے ہیں۔

function getTotalEquity() {
    var exName = exchange.GetName()
    if (exName == "Futures_OKCoin") {
        return getTotalEquity_OKEX_V5()
    } else if (exName == "Futures_Binance") {
        return getTotalEquity_Binance()
    } else {
        throw "不支持该交易所"
    }
}

کچھ مددگار افعال ڈیزائن کریں۔

مین فنکشن اور مین منطق کو ڈیزائن کرنے سے پہلے۔ ہمیں ابھی بھی کچھ تیاری کرنے اور کچھ معاون افعال کو ڈیزائن کرنے کی ضرورت ہے۔

  • تمام موجودہ زیر التواء آرڈرز منسوخ کریں۔
  function cancelAll() {
      while (1) {
          var orders = _C(exchange.GetOrders)
          if (orders.length == 0) {
              break
          }
          for (var i = 0 ; i < orders.length ; i++) {
              exchange.CancelOrder(orders[i].Id, orders[i])
              Sleep(500)
          }
          Sleep(500)
      }
  }

مجھے یقین ہے کہ وہ لوگ جو اکثر FMZ Strategy Square پر حکمت عملی کے مثالی کوڈز کو دیکھتے ہیں وہ اس فنکشن سے بہت واقف ہیں۔ اس کا کام زیر التواء آرڈرز کی موجودہ فہرست حاصل کرنا اور پھر انہیں ایک ایک کرکے منسوخ کرنا ہے۔

  • فیوچر آرڈر آپریشن
  function trade(distance, price, amount) {
      var tradeFunc = null 
      if (distance == "buy") {
          tradeFunc = exchange.Buy
      } else if (distance == "sell") {
          tradeFunc = exchange.Sell
      } else if (distance == "closebuy") {
          tradeFunc = exchange.Sell
      } else {
          tradeFunc = exchange.Buy
      }
      exchange.SetDirection(distance)
      return tradeFunc(price, amount)
  }

  function openLong(price, amount) {
      return trade("buy", price, amount)
  }

  function openShort(price, amount) {
      return trade("sell", price, amount)
  }

  function coverLong(price, amount) {
      return trade("closebuy", price, amount)
  }

  function coverShort(price, amount) {
      return trade("closesell", price, amount)
  }

فیوچر ٹریڈنگ میں چار سمتیں ہیں: لانگ پوزیشن کھولیں (اوپن لانگ)، شارٹ پوزیشن (اوپن شارٹ) کھولیں، لانگ پوزیشن (کور لانگ) بند کریں، اور مختصر پوزیشن (کور شارٹ) بند کریں۔ لہذا ہم نے ان آپریشنز کے مطابق چار آرڈر فنکشنز بنائے۔ اگر آپ صرف آرڈر دینے پر غور کرتے ہیں، تو کئی ضروری عوامل ہیں: سمت، آرڈر کی قیمت، اور آرڈر کی مقدار۔ لہذا ہم نے ایک پروگرام بھی ڈیزائن کیا جس کا نام ہے:tradeہینڈل کرنے کا فنکشن方向(distance)下单价格(price)下单量(amount)تمام آپریشن واضح ہیں۔ لانگ پوزیشن (اوپن لانگ) کھولنے، شارٹ پوزیشن کھولنے (اوپن شارٹ)، لانگ پوزیشن (کور لانگ) کو بند کرنے اور شارٹ پوزیشن (کور شارٹ) کو بند کرنے کے فنکشن کالز کو بالآخر انجام دیا جاتا ہے۔tradeفنکشن اصل فنکشن انجام دیتا ہے، جو کہ طے شدہ سمت، قیمت اور مقدار کے مطابق فیوچر ایکسچینج پر آرڈر دینا ہے۔

مین فنکشن

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

  • ابتدائی کام چونکہ ہمیں آرڈر دینے کی ضرورت ہے، ہمیں آرڈر آئی ڈیز کو ریکارڈ کرنے کے لیے دو عالمی متغیرات کی ضرورت ہے۔
  var buyOrderId = null
  var sellOrderId = null

پھر OKEX_V5 سمولیشن ڈسک کو استعمال کرنے کا اختیار حکمت عملی انٹرفیس کے پیرامیٹرز میں ڈیزائن کیا گیا ہے، لہذا کوڈ میں کچھ پروسیسنگ کرنے کی ضرورت ہے:

  var exName = exchange.GetName()    
  // 切换OKEX V5模拟盘
  if (isSimulate && exName == "Futures_OKCoin") {
      exchange.IO("simulate", true)
  }

انٹرفیس کے پیرامیٹرز میں تمام معلومات کو دوبارہ ترتیب دینے کا آپشن بھی شامل ہے، اس لیے کوڈ میں بھی متعلقہ پروسیسنگ ہونی چاہیے:

  if (isReset) {
      _G(null)
      LogReset(1)
      LogProfitReset()
      LogVacuum()
      Log("重置所有数据", "#FF0000")
  }

ہم صرف دائمی معاہدوں کو چلاتے ہیں، لہذا یہ یہاں سخت کوڈڈ ہے اور صرف دائمی معاہدوں پر سیٹ ہے۔

  exchange.SetContractType("swap")

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

  exchange.SetPrecision(pricePrecision, amountPrecision)
  Log("设置精度", pricePrecision, amountPrecision)

سادہ ڈیٹا ریکوری فنکشن

  if (totalEq == -1 && !IsVirtual()) {
      var recoverTotalEq = _G("totalEq")
      if (!recoverTotalEq) {
          var currTotalEq = getTotalEquity()
          if (currTotalEq) {
              totalEq = currTotalEq
              _G("totalEq", currTotalEq)
          } else {
              throw "获取初始权益失败"
          }
      } else {
          totalEq = recoverTotalEq
      }
  }

اگر آپ حکمت عملی کے چلنے پر ابتدائی کل اکاؤنٹ ایکویٹی بتانا چاہتے ہیں، تو آپ پیرامیٹر سیٹ کر سکتے ہیں۔totalEqاگر اس پیرامیٹر کو -1 پر سیٹ کیا جاتا ہے، تو حکمت عملی کل ایکویٹی ڈیٹا کو پڑھے گی اگر کوئی ذخیرہ شدہ کل ایکویٹی ڈیٹا نہیں ہے، تو موجودہ پڑھی جانے والی کل ایکویٹی کو اسٹریٹیجی چلانے کی کل ایکویٹی کے طور پر استعمال کیا جائے گا۔ ایکویٹی بڑھ جاتی ہے، اس کا مطلب ہے کہ اگر آپ پیسہ کماتے ہیں، لیکن آپ کی کل ایکویٹی کم ہے، اس کا مطلب ہے کہ آپ نے پیسہ کھو دیا ہے۔ اگر کل ایکویٹی ڈیٹا پڑھا جاتا ہے، تو اس ڈیٹا کا استعمال کرتے ہوئے چلنا جاری رکھیں۔

  • بنیادی منطق ابتدائی کام مکمل ہونے کے بعد، ہم آخر کار حکمت عملی کی بنیادی منطق پر آگئے، وضاحت کی سہولت کے لیے، میں نے براہ راست کوڈ کمنٹس میں وضاحت لکھ دی۔
    while (1) {                                  // 策略主要逻辑设计为一个死循环
        var ticker = _C(exchange.GetTicker)      // 首先读取当前行情信息,主要用到最新成交价
        var pos = _C(exchange.GetPosition)       // 读取当前持仓数据
        if (pos.length > 1) {                    // 判断持仓数据,由于这个策略的逻辑,是不太可能同时出现多空持仓的,所以发现同时出现多空持仓就抛出错误
            Log(pos)
            throw "同时有多空持仓"                  // 抛出错误,让策略停止
        }
        // 根据状态而定
        if (pos.length == 0) {                    // 根据持仓状态做出不同操作,pos.length == 0是当没有持仓时
            // 未持仓了,统计一次收益
            if (!IsVirtual()) {
                var currTotalEq = getTotalEquity()
                if (currTotalEq) {
                    LogProfit(currTotalEq - totalEq, "当前总权益:", currTotalEq)
                }
            }

            buyOrderId = openLong(ticker.Last - targetProfit, amount)       // 挂开多仓的买单
            sellOrderId = openShort(ticker.Last + targetProfit, amount)     // 挂开空仓的卖单
        } else if (pos[0].Type == PD_LONG) {   // 有多头持仓,挂单位置、数量有所不同
            var n = 1
            var price = ticker.Last
            buyOrderId = openLong(price - targetProfit * n, amount)
            sellOrderId = coverLong(pos[0].Price + targetProfit, pos[0].Amount)
        } else if (pos[0].Type == PD_SHORT) {   // 有空头持仓,挂单位置、数量有所不同
            var n = 1
            var price = ticker.Last
            buyOrderId = coverShort(pos[0].Price - targetProfit, pos[0].Amount)
            sellOrderId = openShort(price + targetProfit * n, amount)
        }

        if (!sellOrderId || !buyOrderId) {   // 如果有一边挂单失败就取消所有挂单,重来
            cancelAll()
            buyOrderId = null 
            sellOrderId = null
            continue
        } 

        while (1) {  // 挂单完成,开始监控订单
            var isFindBuyId = false 
            var isFindSellId = false
            var orders = _C(exchange.GetOrders)
            for (var i = 0 ; i < orders.length ; i++) {
                if (buyOrderId == orders[i].Id) {
                    isFindBuyId = true 
                }
                if (sellOrderId == orders[i].Id) {
                    isFindSellId = true 
                }               
            }
            if (!isFindSellId && !isFindBuyId) {    // 检测到买卖单都成交了
                cancelAll()
                break
            } else if (!isFindBuyId) {   // 检测到买单成交
                Log("买单成交")
                cancelAll()
                break
            } else if (!isFindSellId) {  // 检测到卖单成交
                Log("卖单成交")
                cancelAll()
                break
            }
            LogStatus(_D())
            Sleep(3000)
        }
        Sleep(500)
    }

پوری منطق اور ڈیزائن کی وضاحت کردی گئی ہے۔

بیک ٹیسٹنگ

حکمت عملی کو 19 مئی کو مارکیٹ کی صورتحال کا تجربہ کرنے دیں۔

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

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

یہ دیکھا جا سکتا ہے کہ Martingale حکمت عملی میں اب بھی کچھ خطرات ہیں۔

آپ حقیقی تجارت کے لیے OKEX V5 ڈیمو آزما سکتے ہیں۔

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

حکمت عملی کا پتہ: https://www.fmz.com/strategy/294957

حکمت عملی بنیادی طور پر سیکھنے کے لیے استعمال ہوتی ہے، اس لیے حقیقی رقم کو احتیاط کے ساتھ استعمال کریں ~!