हेजिंग रणनीतियाँ रणनीति डिजाइन में शुरुआती लोगों के लिए बहुत अच्छी अभ्यास रणनीतियाँ हैं। यह लेख एक सरल लेकिन जीवित क्रिप्टोक्यूरेंसी स्पॉट हेजिंग रणनीति को लागू करता है, उम्मीद है कि शुरुआती कुछ डिजाइन अनुभव सीख सकते हैं।
सबसे पहले, यह स्पष्ट है कि डिजाइन की जाने वाली रणनीति एक क्रिप्टोक्यूरेंसी स्पॉट हेजिंग रणनीति है। हम सबसे सरल हेजिंग रणनीति डिजाइन करते हैं। हम दो स्पॉट एक्सचेंजों के बीच ही उच्च मूल्य के साथ एक्सचेंज पर बेचते हैं, और अंतर लेने के लिए कम कीमत के साथ एक्सचेंज पर खरीदते हैं। जब उच्च कीमत वाले एक्सचेंजों में सभी नामित सिक्के होते हैं (क्योंकि उच्च कीमत वाले सिक्के बेचे जाते हैं), और कम कीमत वाले एक्सचेंजों में सभी सिक्के होते हैं (कम कीमत वाले सिक्के खरीदे जाते हैं), तो इसे हेज नहीं किया जा सकता है। इस समय, हम केवल मूल्य उलट को हेज करने के लिए इंतजार कर सकते हैं।
हेजिंग के दौरान, ऑर्डर की कीमत और मात्रा को एक्सचेंज द्वारा सीमित किया जाता है, और न्यूनतम ऑर्डर मात्रा पर भी एक सीमा होती है। न्यूनतम सीमा के अलावा, हेजिंग में रणनीति को एक बार में अधिकतम ऑर्डर वॉल्यूम पर भी विचार करने की आवश्यकता होती है। यदि ऑर्डर वॉल्यूम बहुत बड़ा है, तो पर्याप्त ऑर्डर वॉल्यूम नहीं होगा। यह भी विचार करना आवश्यक है कि यदि दो एक्सचेंज-मुद्रीकृत सिक्के अलग हैं तो विनिमय दर को कैसे परिवर्तित किया जाए। हेजिंग के दौरान, हैंडलिंग शुल्क और ऑर्डर लेने वाले का फिसलना सभी लेनदेन लागत हैं, जब तक कोई मूल्य अंतर नहीं है, तब तक हेज नहीं किया जा सकता है। इसलिए, हेजिंग मूल्य अंतर का एक ट्रिगर मूल्य भी होता है। यदि यह एक निश्चित मूल्य अंतर से कम है, तो हेजिंग खो जाएगी।
इन विचारों के आधार पर, रणनीति को कई मापदंडों के साथ डिजाइन करने की आवश्यकता हैः
hedgeDiffPrice
, जब अंतर इस मूल्य से अधिक हो जाता है, तो हेजिंग ऑपरेशन शुरू हो जाता है।minHedgeAmount
, न्यूनतम ऑर्डर राशि (सिक्के) जिसे हेज किया जा सकता है।maxHedgeAmount
, एक हेजिंग के लिए अधिकतम ऑर्डर राशि (सिक्के) ।pricePrecisionA
, एक्सचेंज ए द्वारा रखे गए ऑर्डर मूल्य की सटीकता (दशमलव स्थानों की संख्या) ।amountPrecisionA
, एक्सचेंज ए द्वारा दिए गए ऑर्डर की राशि की सटीकता (दशमलव स्थानों की संख्या) ।pricePrecisionB
, एक्सचेंज बी द्वारा रखे गए ऑर्डर मूल्य की सटीकता (दशमलव स्थानों की संख्या) ।amountPrecisionB
, एक्सचेंज बी द्वारा दिए गए ऑर्डर की राशि की सटीकता (दशमलव स्थानों की संख्या) ।rateA
, पहले जोड़े गए विनिमय वस्तु का विनिमय दर रूपांतरण, डिफ़ॉल्ट 1 है, परिवर्तित नहीं किया गया है।rateB
, दूसरे जोड़े गए विनिमय वस्तु का विनिमय दर रूपांतरण, डिफ़ॉल्ट 1 है, परिवर्तित नहीं किया गया।हेजिंग रणनीति को दो खातों में सिक्कों की संख्या को अपरिवर्तित रखने की आवश्यकता है (यानी, किसी भी दिशा में पद नहीं रखना, और तटस्थता बनाए रखना), इसलिए रणनीति में संतुलन तर्क की आवश्यकता होती है ताकि संतुलन का हमेशा पता लगाया जा सके। संतुलन की जांच करते समय, दो एक्सचेंजों से परिसंपत्ति डेटा प्राप्त करना अपरिहार्य है। हमें उपयोग करने के लिए एक फ़ंक्शन लिखने की आवश्यकता है।
function updateAccs(arrEx) {
var ret = []
for (var i = 0 ; i < arrEx.length ; i++) {
var acc = arrEx[i].GetAccount()
if (!acc) {
return null
}
ret.push(acc)
}
return ret
}
आदेश देने के बाद, यदि कोई पूरा आदेश नहीं है, तो हमें इसे समय पर रद्द करने की आवश्यकता है, और आदेश को लंबित नहीं रखा जा सकता है। इस ऑपरेशन को बैलेंस मॉड्यूल और हेजिंग लॉजिक दोनों में संसाधित करने की आवश्यकता है, इसलिए ऑर्डर पूर्ण निकासी फ़ंक्शन को डिज़ाइन करना भी आवश्यक है।
function cancelAll() {
_.each(exchanges, function(ex) {
while (true) {
var orders = _C(ex.GetOrders)
if (orders.length == 0) {
break
}
for (var i = 0 ; i < orders.length ; i++) {
ex.CancelOrder(orders[i].Id, orders[i])
Sleep(500)
}
}
})
}
सिक्कों की संख्या को संतुलित करते समय, हमें एक निश्चित गहराई के डेटा में सिक्कों की एक निश्चित संख्या के लिए संचित मूल्य खोजने की आवश्यकता होती है, इसलिए हमें इसे संभालने के लिए इस तरह के एक फ़ंक्शन की आवश्यकता होती है।
function getDepthPrice(depth, side, amount) {
var arr = depth[side]
var sum = 0
var price = null
for (var i = 0 ; i < arr.length ; i++) {
var ele = arr[i]
sum += ele.Amount
if (sum >= amount) {
price = ele.Price
break
}
}
return price
}
फिर हमें विशिष्ट हेजिंग ऑर्डर ऑपरेशन को डिजाइन और लिखने की आवश्यकता है, जिसे समवर्ती ऑर्डर रखने के लिए डिज़ाइन किया जाना चाहिएः
function hedge(buyEx, sellEx, price, amount) {
var buyRoutine = buyEx.Go("Buy", price, amount)
var sellRoutine = sellEx.Go("Sell", price, amount)
Sleep(500)
buyRoutine.wait()
sellRoutine.wait()
}
अंत में, चलो संतुलन समारोह के डिजाइन को पूरा करते हैं, जो थोड़ा जटिल है।
function keepBalance(initAccs, nowAccs, depths) {
var initSumStocks = 0
var nowSumStocks = 0
_.each(initAccs, function(acc) {
initSumStocks += acc.Stocks + acc.FrozenStocks
})
_.each(nowAccs, function(acc) {
nowSumStocks += acc.Stocks + acc.FrozenStocks
})
var diff = nowSumStocks - initSumStocks
// Calculate the currency difference
if (Math.abs(diff) > minHedgeAmount && initAccs.length == nowAccs.length && nowAccs.length == depths.length) {
var index = -1
var available = []
var side = diff > 0 ? "Bids" : "Asks"
for (var i = 0 ; i < nowAccs.length ; i++) {
var price = getDepthPrice(depths[i], side, Math.abs(diff))
if (side == "Bids" && nowAccs[i].Stocks > Math.abs(diff)) {
available.push(i)
} else if (price && nowAccs[i].Balance / price > Math.abs(diff)) {
available.push(i)
}
}
for (var i = 0 ; i < available.length ; i++) {
if (index == -1) {
index = available[i]
} else {
var priceIndex = getDepthPrice(depths[index], side, Math.abs(diff))
var priceI = getDepthPrice(depths[available[i]], side, Math.abs(diff))
if (side == "Bids" && priceIndex && priceI && priceI > priceIndex) {
index = available[i]
} else if (priceIndex && priceI && priceI < priceIndex) {
index = available[i]
}
}
}
if (index == -1) {
Log("unable to balance")
} else {
// balance order
var price = getDepthPrice(depths[index], side, Math.abs(diff))
if (price) {
var tradeFunc = side == "Bids" ? exchanges[index].Sell : exchanges[index].Buy
tradeFunc(price, Math.abs(diff))
} else {
Log("invalid price", price)
}
}
return false
} else if (!(initAccs.length == nowAccs.length && nowAccs.length == depths.length)) {
Log("errors:", "initAccs.length:", initAccs.length, "nowAccs.length:", nowAccs.length, "depths.length:", depths.length)
return true
} else {
return true
}
}
इन कार्यों को रणनीति की आवश्यकताओं के अनुसार डिजाइन करने के बाद, फिर रणनीति के मुख्य कार्य को डिजाइन करना शुरू करें।
एफएमजेड प्लेटफॉर्म पर, रणनीति कोmain
कार्य की शुरुआत में।main
समारोह, हम रणनीति के कुछ आरंभिक कार्य करना है.
एक्सचेंज ऑब्जेक्ट का नाम चूंकि रणनीति में कई कार्यों को विनिमय वस्तुओं का उपयोग करना पड़ता है, जैसे कि बाजार उद्धरण प्राप्त करना, आदेश देना आदि। इसलिए हर बार एक लंबे नाम का उपयोग करना बोझिल होगा, टिप इसके बजाय एक सरल नाम का उपयोग करना है, उदाहरण के लिएः
var exA = exchanges[0]
var exB = exchanges[1]
इससे बाद में कोड लिखना आसान हो जाता है।
विनिमय दर, सटीकता से संबंधित डिजाइन
// precision, exchange rate settings
if (rateA != 1) {
// set exchange rate A
exA.SetRate(rateA)
Log("Exchange A sets the exchange rate:", rateA, "#FF0000")
}
if (rateB != 1) {
// set exchange rate B
exB.SetRate(rateB)
Log("Exchange B sets the exchange rate:", rateB, "#FF0000")
}
exA.SetPrecision(pricePrecisionA, amountPrecisionA)
exB.SetPrecision(pricePrecisionB, amountPrecisionB)
यदि विनिमय दर मापदंडोंrateA
, rateB
1 पर सेट हैं (डिफ़ॉल्ट 1 है), यानी,rateA != 1
याrateB != 1
ट्रिगर नहीं होगा, इसलिए विनिमय दर रूपांतरण सेट नहीं किया जाएगा।
सभी डेटा रीसेट करें
कभी कभी यह सभी लॉग को हटाने के लिए आवश्यक है और रिकॉर्ड डेटा साफ़ जब रणनीति शुरू होता है. आप एक रणनीति इंटरफ़ेस पैरामीटर डिजाइन कर सकते हैंisReset
, और रणनीति के आरंभ भाग में रीसेट कोड डिजाइन, उदाहरण के लिएः
if (isReset) { // When isReset is true, reset the data
_G(null)
LogReset(1)
LogProfitReset()
LogVacuum()
Log("reset all data", "#FF0000")
}
मूल खाता डेटा पुनर्स्थापित करें, चालू खाता डेटा अद्यतन करें
संतुलन का आकलन करने के लिए रणनीति को चालू खाते के साथ तुलना के लिए प्रारंभिक खाता परिसंपत्तियों को लगातार दर्ज करने की आवश्यकता होती है।nowAccs
चालू खाता डेटा रिकॉर्ड करने के लिए प्रयोग किया जाता है, हम सिर्फ डिजाइन किया है समारोह का उपयोगupdateAccs
वर्तमान विनिमय के खाते का डेटा प्राप्त करने के लिए।initAccs
इसका उपयोग प्रारंभिक खाता स्थिति (मुद्राओं की संख्या, मुद्राओं की संख्या, आदि) को एक्सचेंजों A और B पर रिकॉर्ड करने के लिए किया जाता है।initAccs
, का प्रयोग करें_G()
फ़ंक्शन को पहले पुनर्स्थापित करने के लिए ( _G फ़ंक्शन डेटा को लगातार रिकॉर्ड करेगा, और रिकॉर्ड किए गए डेटा को फिर से लौटा सकता है, विवरण के लिए एपीआई प्रलेखन देखेंः [लिंक](https://www.fmz.com/api#_gk-v)), यदि क्वेरी काम नहीं करती है, तो मूल्य निर्दिष्ट करने के लिए चालू खाता जानकारी का उपयोग करें और_G
रिकॉर्ड करने के लिए फ़ंक्शन।
जैसे कि निम्न कोडः
var nowAccs = _C(updateAccs, exchanges)
var initAccs = _G("initAccs")
if (!initAccs) {
initAccs = nowAccs
_G("initAccs", initAccs)
}
मुख्य लूप में कोड रणनीति तर्क के निष्पादन के प्रत्येक दौर की प्रक्रिया है, जिसे रणनीति के मुख्य लूप को बनाने के लिए बार-बार निष्पादित किया जाता है। आइए मुख्य लूप में कार्यक्रम के प्रत्येक निष्पादन की प्रक्रिया पर एक नज़र डालें।
बाजार के आंकड़े प्राप्त करें और बाजार के आंकड़ों की वैधता का आकलन करें
var ts = new Date().getTime()
var depthARoutine = exA.Go("GetDepth")
var depthBRoutine = exB.Go("GetDepth")
var depthA = depthARoutine.wait()
var depthB = depthBRoutine.wait()
if (!depthA || !depthB || depthA.Asks.length == 0 || depthA.Bids.length == 0 || depthB.Asks.length == 0 || depthB.Bids.length == 0) {
Sleep(500)
continue
}
यहाँ हम देख सकते हैं कि समवर्ती समारोहexchange.Go
FMZ मंच के समवर्ती वस्तुओं बनाने के लिए प्रयोग किया जाता हैdepthARoutine
, depthBRoutine
कि कॉलGetDepth()
जब इन दो समवर्ती वस्तुओं बनाया जाता है,GetDepth()
इंटरफ़ेस तुरंत बुलाया जाता है, और गहराई डेटा के लिए दोनों अनुरोध एक्सचेंज को भेजे जाते हैं।
तो कॉलwait()
विधिdepthARoutine
, depthBRoutine
गहराई के आंकड़े प्राप्त करने के लिए वस्तुओं।
गहराई के आंकड़ों को प्राप्त करने के बाद, इसकी वैधता निर्धारित करने के लिए गहराई के आंकड़ों की जांच करना आवश्यक है।continue
मुख्य लूप को फिर से निष्पादित करने के लिए कथन ट्रिगर किया जाता है.
उपयोग करेंspread value
पैरामीटर याspread ratio
पैरामीटर?
var targetDiffPrice = hedgeDiffPrice
if (diffAsPercentage) {
targetDiffPrice = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentage
}
मापदंडों के संदर्भ में, हमने ऐसा डिजाइन किया हैः FMZ के मापदंडों को किया जा सकता हैदिखावायाछुपानाएक पैरामीटर पर आधारित है, तो हम एक पैरामीटर तय करने के लिए उपयोग करने के लिए या नहीं कर सकते हैंprice spread
, याspread ratio
.
एक पैरामीटरdiffAsPercentage
इस पैरामीटर के आधार पर दिखाने या छिपाने के लिए अन्य दो पैरामीटर सेटिंग्स हैंःhedgeDiffPrice@!diffAsPercentage
, जो तब प्रदर्शित होता है जबdiffAsPercentage
गलत है।hedgeDiffPercentage@diffAsPercentage
, जो तब प्रदर्शित होता है जबdiffAsPercentage
सच है।
इस डिजाइन के बाद, हमने जांच कीdiffAsPercentage
पैरामीटर, जो मूल्य अंतर अनुपात के आधार पर हेज ट्रिगर स्थिति है।diffAsPercentage
पैरामीटर की जाँच की जाती है, मूल्य अंतर से हेज ट्रिगर होता है।
हेजिंग ट्रिगर की शर्तें निर्धारित करें
if (depthA.Bids[0].Price - depthB.Asks[0].Price > targetDiffPrice && Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount) >= minHedgeAmount) { // A -> B market conditions are met
var price = (depthA.Bids[0].Price + depthB.Asks[0].Price) / 2
var amount = Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount)
if (nowAccs[0].Stocks > minHedgeAmount && nowAccs[1].Balance / price > minHedgeAmount) {
amount = Math.min(amount, nowAccs[0].Stocks, nowAccs[1].Balance / price, maxHedgeAmount)
Log("trigger A->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, price, amount, nowAccs[1].Balance / price, nowAccs[0].Stocks) // Tips
hedge(exB, exA, price, amount)
cancelAll()
lastKeepBalanceTS = 0
isTrade = true
}
} else if (depthB.Bids[0].Price - depthA.Asks[0].Price > targetDiffPrice && Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount) >= minHedgeAmount) { // B -> A market conditions are met
var price = (depthB.Bids[0].Price + depthA.Asks[0].Price) / 2
var amount = Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount)
if (nowAccs[1].Stocks > minHedgeAmount && nowAccs[0].Balance / price > minHedgeAmount) {
amount = Math.min(amount, nowAccs[1].Stocks, nowAccs[0].Balance / price, maxHedgeAmount)
Log("trigger B->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, price, amount, nowAccs[0].Balance / price, nowAccs[1].Stocks) // Tips
hedge(exA, exB, price, amount)
cancelAll()
lastKeepBalanceTS = 0
isTrade = true
}
}
हेजिंग ट्रिगर की शर्तें इस प्रकार हैं:
isTrade
यदि हेजिंग ट्रिगर हो जाती है, तो चर को सेट किया जाता हैtrue
. और वैश्विक चर रीसेट करेंlastKeepBalanceTS
0 पर (lastKeepBalanceTS का उपयोग अंतिम संतुलन ऑपरेशन के टाइमस्टैम्प को चिह्नित करने के लिए किया जाता है, इसे 0 पर सेट करने से संतुलन ऑपरेशन तुरंत ट्रिगर हो जाएगा), और फिर सभी लंबित ऑर्डर रद्द करें।संतुलन संचालन
if (ts - lastKeepBalanceTS > keepBalanceCyc * 1000) {
nowAccs = _C(updateAccs, exchanges)
var isBalance = keepBalance(initAccs, nowAccs, [depthA, depthB])
cancelAll()
if (isBalance) {
lastKeepBalanceTS = ts
if (isTrade) {
var nowBalance = _.reduce(nowAccs, function(sumBalance, acc) {return sumBalance + acc.Balance}, 0)
var initBalance = _.reduce(initAccs, function(sumBalance, acc) {return sumBalance + acc.Balance}, 0)
LogProfit(nowBalance - initBalance, nowBalance, initBalance, nowAccs)
isTrade = false
}
}
}
यह देखा जा सकता है कि संतुलन समारोह आवधिक रूप से निष्पादित किया जाता है, लेकिन अगरlastKeepBalanceTS
हेजिंग ऑपरेशन के शुरू होने के बाद 0 पर रीसेट किया जाता है, तो संतुलन ऑपरेशन तुरंत शुरू हो जाएगा। लाभ एक सफल संतुलन के बाद गणना की जाएगी।
स्थिति पट्टी जानकारी
LogStatus(_D(), "A->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, " B->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, " targetDiffPrice:", targetDiffPrice, "\n",
"current A, Stocks:", nowAccs[0].Stocks, "FrozenStocks:", nowAccs[0].FrozenStocks, "Balance:", nowAccs[0].Balance, "FrozenBalance", nowAccs[0].FrozenBalance, "\n",
"current B, Stocks:", nowAccs[1].Stocks, "FrozenStocks:", nowAccs[1].FrozenStocks, "Balance:", nowAccs[1].Balance, "FrozenBalance", nowAccs[1].FrozenBalance, "\n",
"initial A, Stocks:", initAccs[0].Stocks, "FrozenStocks:", initAccs[0].FrozenStocks, "Balance:", initAccs[0].Balance, "FrozenBalance", initAccs[0].FrozenBalance, "\n",
"initial B, Stocks:", initAccs[1].Stocks, "FrozenStocks:", initAccs[1].FrozenStocks, "Balance:", initAccs[1].Balance, "FrozenBalance", initAccs[1].FrozenBalance)
स्थिति पट्टी डिजाइन में विशेष रूप से जटिल नहीं है। यह वर्तमान समय, एक्सचेंज ए से एक्सचेंज बी तक मूल्य अंतर और एक्सचेंज बी से एक्सचेंज ए तक मूल्य अंतर प्रदर्शित करता है। और यह वर्तमान हेज लक्ष्य स्प्रेड, एक्सचेंज ए खाते और एक्सचेंज बी खाते के परिसंपत्ति डेटा प्रदर्शित करता है।
मापदंडों के संदर्भ में, हमने रूपांतरण दर मूल्य मापदंड को डिजाइन किया, और हमने विनिमय दर रूपांतरण को भी डिजाइन कियाmain
यह ध्यान दिया जाना चाहिए किSetRate
विनिमय दर रूपांतरण फ़ंक्शन को पहले निष्पादित करने की आवश्यकता है।
क्योंकि यह कार्य दो पहलुओं को प्रभावित करता हैः
BTC_USDT
, मूल्य इकाई हैUSDT
, और खाता परिसंपत्तियों में उपलब्ध मुद्रा भी हैUSDT
. अगर मैं मूल्य CNY में परिवर्तित करना चाहते हैं, सेटexchange.SetRate(6.8)
कोड में सभी कार्यों द्वारा प्राप्त डेटा को परिवर्तित करने के लिएexchange
विनिमय वस्तु CNY में।
किस मुद्रा में परिवर्तित करने के लिए, पास करेंवर्तमान मुद्रा से लक्ष्य मुद्रा में विनिमय दरके लिएSetRate
function.पूर्ण रणनीति:विभिन्न मुद्राओं की स्पॉट हेजिंग रणनीति (ट्यूटोरियल)