हाल ही में, एफएमजेड आधिकारिक समूह में कई मार्टिंगेल रणनीतियों पर चर्चा की गई है, और मंच पर क्रिप्टोक्यूरेंसी अनुबंधों की कई मार्टिंगेल रणनीतियाँ नहीं हैं। इसलिए, मैंने क्रिप्टोक्यूरेंसी वायदा के लिए एक सरल मार्टिंगेल रणनीति डिजाइन करने का अवसर लिया। इसे मार्टिंगेल रणनीति क्यों कहा जाता है? क्योंकि मार्टिंगेल रणनीति के संभावित जोखिम वास्तव में छोटे नहीं हैं, इसलिए इसे मार्टिंगेल रणनीति के अनुसार बिल्कुल डिज़ाइन नहीं किया गया है। हालांकि, इस प्रकार की रणनीति में अभी भी बहुत सारे जोखिम हैं, और मार्टिंगेल-प्रकार की रणनीति की पैरामीटर सेटिंग्स जोखिम से निकटता से संबंधित हैं, और जोखिम को नजरअंदाज नहीं किया जाना चाहिए।
यह लेख मुख्य रूप से मार्टिन-प्रकार की रणनीतियों के डिजाइन से समझाता है और सीखता है। चूंकि रणनीति विचार बहुत स्पष्ट है, एफएमजेड के उपयोगकर्ता के रूप में, हम रणनीति डिजाइन को अधिक मानते हैं।
कुल इक्विटी का उपयोग अक्सर क्रिप्टोक्यूरेंसी वायदा रणनीतियों को डिजाइन करते समय किया जाता है। ऐसा इसलिए है क्योंकि रिटर्न की गणना की जानी चाहिए, खासकर जब आपको फ्लोटिंग रिटर्न की गणना करने की आवश्यकता होती है। चूंकि स्थिति मार्जिन के साथ कब्जा कर ली गई है, इसलिए लंबित आदेश भी कब्जा कर लिया गया है। इस समय, एपीआई इंटरफ़ेसexchange.GetAccount()
एफएमजेड प्लेटफॉर्म के उपलब्ध परिसंपत्तियों और लंबित आदेश जमे हुए परिसंपत्तियों को प्राप्त करने के लिए कहा जाता है। वास्तव में, अधिकांश क्रिप्टोक्यूरेंसी वायदा एक्सचेंजों कुल इक्विटी का डेटा प्रदान करते हैं, लेकिन यह विशेषता एफएमजेड पर समान रूप से पैक नहीं की गई है।
तो हम विभिन्न एक्सचेंजों के अनुसार इन आंकड़ों को प्राप्त करने के लिए कार्यों को डिजाइन करते हैंः
// OKEX V5 obtain total equity
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("failed to obtain the total equity of the account!")
return null
}
}
return totalEquity
}
// Binance futures
function getTotalEquity_Binance() {
var totalEquity = null
var ret = exchange.GetAccount()
if (ret) {
try {
totalEquity = parseFloat(ret.Info.totalWalletBalance)
} catch(e) {
Log("failed to obtain the total equity of the account!")
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 "This exchange is not supported"
}
}
मुख्य कार्य और मुख्य तर्क को डिजाइन करने से पहले, हमें कुछ तैयारी करने और कुछ सहायक कार्यों को डिजाइन करने की आवश्यकता है।
सभी लंबित आदेश रद्द करें
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)
}
}
यह फ़ंक्शन उन लोगों के लिए परिचित है जो अक्सर एफएमजेड रणनीति वर्ग पर रणनीति उदाहरण कोड पढ़ते हैं, और कई रणनीतियों ने इसी तरह के डिजाइन का उपयोग किया है। फ़ंक्शन वर्तमान लंबित आदेश सूची प्राप्त करना है, और फिर उन्हें एक-एक करके रद्द करना है।
फ्यूचर्स के लिए प्लेसमेंट ऑपरेशन
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
निर्दिष्ट हैं।
openLong, openShort, coverLong और coverShort के लिए फ़ंक्शन कॉल अंततःtrade
कार्य, अर्थात, निर्धारित दूरी, मूल्य और मात्रा के आधार पर वायदा विनिमय पर आदेश देना।
रणनीति का विचार बहुत सरल है, वर्तमान मूल्य को आधार रेखा के रूप में लें, और एक निश्चित दूरी ऊपर या नीचे पर बेच (लघु) और खरीद (लंबी) आदेश रखें। एक बार लेनदेन पूरा हो जाने के बाद, सभी शेष आदेश रद्द कर दिए जाएंगे, और फिर स्थिति की कीमत के अनुसार एक निश्चित दूरी पर एक नया समापन आदेश रखा जाएगा, और एक वृद्धि आदेश अद्यतन वर्तमान मूल्य पर रखा जाएगा, लेकिन अतिरिक्त पदों के लिए आदेश मात्रा दोगुनी नहीं होगी।
प्रारंभिक कार्य लंबित आदेश के कारण, हमें आदेश आईडी रिकॉर्ड करने के लिए दो वैश्विक चर की आवश्यकता है।
var buyOrderId = null
var sellOrderId = null
फिर रणनीति इंटरफ़ेस मापदंडों OKEX_V5 सिम्युलेटेड बॉट विकल्प का उपयोग करने के लिए डिजाइन कर रहे हैं, तो कुछ प्रसंस्करण कोड में किया जाना चाहिएः
var exName = exchange.GetName()
// Switch OKEX V5 simulated bot
if (isSimulate && exName == "Futures_OKCoin") {
exchange.IO("simulate", true)
}
इंटरफेस पैरामीटर में सभी जानकारी को रीसेट करने का विकल्प भी है, इसलिए कोड में संबंधित प्रसंस्करण होना चाहिएः
if (isReset) {
_G(null)
LogReset(1)
LogProfitReset()
LogVacuum()
Log("reset all data", "#FF0000")
}
हम केवल शाश्वत अनुबंध चलाते हैं, इसलिए लेखन यहां तय है और केवल शाश्वत पर सेट है।
exchange.SetContractType("swap")
फिर हमें ऑर्डर मूल्य और ऑर्डर राशि की सटीकता पर भी विचार करने की आवश्यकता है। यदि सटीकता ठीक से सेट नहीं की जाती है, तो रणनीति गणना प्रक्रिया के दौरान सटीकता खो जाएगी। यदि डेटा में बड़ी संख्या में दशमलव स्थान हैं, तो एक्सचेंज इंटरफ़ेस द्वारा ऑर्डर को अस्वीकार करना आसान है।
exchange.SetPrecision(pricePrecision, amountPrecision)
Log("set precision", pricePrecision, amountPrecision)
डिजाइन द्वारा सरल डेटा रिकवरी
if (totalEq == -1 && !IsVirtual()) {
var recoverTotalEq = _G("totalEq")
if (!recoverTotalEq) {
var currTotalEq = getTotalEquity()
if (currTotalEq) {
totalEq = currTotalEq
_G("totalEq", currTotalEq)
} else {
throw "failed to obtain initial equity"
}
} else {
totalEq = recoverTotalEq
}
}
यदि आप रणनीति चल रहा है जब खाते के प्रारंभिक कुल इक्विटी निर्दिष्ट करना चाहते हैं, तो आप पैरामीटर सेट कर सकते हैंtotalEq
. यदि यह पैरामीटर -1 पर सेट है, तो रणनीति संग्रहीत कुल इक्विटी डेटा को पढ़ेगी। यदि कोई संग्रहीत कुल इक्विटी डेटा नहीं है, तो वर्तमान पढ़ी गई कुल इक्विटी का उपयोग प्रगति चल रही रणनीति की प्रारंभिक कुल इक्विटी के रूप में किया जाता है। उसके बाद, कुल इक्विटी में वृद्धि लाभ का संकेत देती है, और कुल इक्विटी में कमी नुकसान का संकेत देती है। यदि कुल इक्विटी डेटा पढ़ा जाता है, तो रणनीति इस डेटा के साथ चलती रहेगी।
मुख्य तर्क प्रारंभिक कार्य पूरा होने के बाद, अंत में हम रणनीति के मुख्य तर्क भाग में आए। स्पष्टीकरण की सुविधा के लिए, मैंने निर्देशों को सीधे कोड टिप्पणियों पर लिखा।
while (1) { // The main logic of the strategy is designed as an infinite loop
var ticker = _C(exchange.GetTicker) // Read the current market information first, mainly using the latest transaction price
var pos = _C(exchange.GetPosition) // Read current position data
if (pos.length > 1) { // Judging the position data, because of the logic of this strategy, it is unlikely that long and short positions will appear at the same time, so if there are long and short positions at the same time, an error will be thrown
Log(pos)
throw "Simultaneous long and short positions" // Throw an error to stop the strategy
}
//Depends on status
if (pos.length == 0) { // Make different operations according to the position status, when there is no position, pos.length == 0
// If you have not held a position, count the profit once
if (!IsVirtual()) {
var currTotalEq = getTotalEquity()
if (currTotalEq) {
LogProfit(currTotalEq - totalEq, "current total equity:", currTotalEq)
}
}
buyOrderId = openLong(ticker.Last - targetProfit, amount) // Open a buy order for a long position
sellOrderId = openShort(ticker.Last + targetProfit, amount) // Open a short sell order
} else if (pos[0].Type == PD_LONG) { // For long positions, the position and quantity of pending orders are different
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) { // For short positions, the position and quantity of pending orders are different
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) { // If one side of the pending order fails, cancel all pending orders and start over
cancelAll()
buyOrderId = null
sellOrderId = null
continue
}
while (1) { // The pending order is completed, start monitoring the order
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) { // Detected that both buy and sell orders have been filled
cancelAll()
break
} else if (!isFindBuyId) { // Detected buy order closing
Log("buy order closing")
cancelAll()
break
} else if (!isFindSellId) { // Detected sell order closing
Log("sell order closing")
cancelAll()
break
}
LogStatus(_D())
Sleep(3000)
}
Sleep(500)
}
इसका पूरा तर्क और डिजाइन समझाया गया है।
रणनीति को 19 मई के बाजार से गुजरने दें।
यह देखा जा सकता है कि मार्टिंगेल रणनीति में अभी भी कुछ जोखिम हैं।
असली बॉट OKEX V5 सिमुलेशन बॉट के साथ चलाया जा सकता है
रणनीतिक पता:https://www.fmz.com/strategy/294957
रणनीतियों का उपयोग मुख्य रूप से सीखने के लिए किया जाता है, और असली पैसे का उपयोग सावधानी से किया जाना चाहिए~!