হেজিং কৌশলগুলি কৌশল নকশায় নতুনদের জন্য খুব ভাল অনুশীলন কৌশল। এই নিবন্ধটি একটি সহজ কিন্তু লাইভ ক্রিপ্টোকারেন্সি স্পট হেজিং কৌশল বাস্তবায়ন করে, আশা করে যে নতুনরা কিছু নকশা অভিজ্ঞতা শিখতে পারে।
সর্বোপরি, এটি স্পষ্ট যে ডিজাইন করা কৌশলটি একটি ক্রিপ্টোকারেন্সি স্পট হেজিং কৌশল। আমরা সবচেয়ে সহজ হেজিং কৌশলটি ডিজাইন করি। আমরা কেবলমাত্র দুটি স্পট এক্সচেঞ্জের মধ্যে উচ্চতর দামের বিনিময়ে বিক্রি করি এবং পার্থক্য নিতে কম দামের বিনিময়ে কিনে থাকি। যখন উচ্চতর দামের বিনিময়ে সমস্ত নামযুক্ত মুদ্রা থাকে (কারণ উচ্চতর দামের মুদ্রা বিক্রি হয়), এবং কম দামের বিনিময়ে সমস্ত মুদ্রা থাকে (নিম্ন দামের মুদ্রা কেনা হয়), এটি হেজ করা যায় না। এই সময়ে, আমরা কেবলমাত্র মূল্য বিপরীতের জন্য হেজিংয়ের জন্য অপেক্ষা করতে পারি।
হিজিংয়ের সময়, অর্ডারের দাম এবং পরিমাণ এক্সচেঞ্জ দ্বারা সীমাবদ্ধ থাকে এবং সর্বনিম্ন অর্ডার পরিমাণেরও একটি সীমা রয়েছে। সর্বনিম্ন সীমা ছাড়াও, হিজিংয়ের কৌশলটি একবারে সর্বাধিক অর্ডার পরিমাণ বিবেচনা করতে হবে। যদি অর্ডার ভলিউম খুব বড় হয় তবে পর্যাপ্ত অর্ডার ভলিউম থাকবে না। দুটি এক্সচেঞ্জ-মুদ্রা আলাদা হলে বিনিময় হার কীভাবে রূপান্তর করা যায় তাও বিবেচনা করা দরকার। হিজিংয়ের সময়, হ্যান্ডলিং ফি এবং অর্ডার গ্রহণকারীর স্লিপজ হ'ল সমস্ত লেনদেনের ব্যয়, যতক্ষণ না দামের পার্থক্য রয়েছে ততক্ষণ হিজিং করা যায় না। অতএব, হিজিংয়ের দামের পার্থক্যেরও একটি ট্রিগার মান রয়েছে। যদি এটি একটি নির্দিষ্ট দামের পার্থক্যের চেয়ে কম হয় তবে হিজিং হারাবে।
এই বিবেচনার ভিত্তিতে, কৌশলটি বেশ কয়েকটি পরামিতি সহ ডিজাইন করা দরকারঃ
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
}
}
পরিকল্পনার প্রয়োজনীয়তা অনুযায়ী এই ফাংশনগুলি ডিজাইন করার পরে, পরিকল্পনার মূল ফাংশনটি ডিজাইন করা শুরু করুন।
FMZ প্ল্যাটফর্মে, কৌশলটিmain
কর্মের শুরুতেmain
ফাংশন, আমরা কৌশল কিছু initialization কাজ করতে হবে.
এক্সচেঞ্জ অবজেক্ট নাম যেহেতু কৌশল অনেক অপারেশন যেমন বাজার কোট পেতে, অর্ডার স্থাপন ইত্যাদি বিনিময় বস্তু ব্যবহার করতে হবে. তাই এটি একটি দীর্ঘ নাম ব্যবহার করতে প্রতিটি সময় জটিল হবে, টিপ পরিবর্তে একটি সহজ নাম ব্যবহার করা হয়, উদাহরণস্বরূপঃ
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
সেট করা আছে ১ (ডিফল্ট হল ১), অর্থাৎ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
এটি অ্যাকাউন্টের প্রাথমিক অবস্থা (মুদ্রার সংখ্যা, মুদ্রা নামকরণ করা মুদ্রার সংখ্যা ইত্যাদি) রেকর্ড করতে ব্যবহৃত হয়।initAccs
, ব্যবহার করুন_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
০ (lastKeepBalanceTS ব্যবহার করা হয় শেষ ব্যালেন্সিং অপারেশনের টাইমস্ট্যাম্প চিহ্নিত করতে, এটি ০ এ সেট করলে অবিলম্বে ব্যালেন্সিং অপারেশন শুরু হবে), এবং তারপরে সমস্ত অপেক্ষমান অর্ডার বাতিল করুন।ব্যালেন্সিং অপারেশন
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
যদি হিজিং অপারেশন শুরু হওয়ার পর এটি শূন্যে পুনরায় সেট করা হয়, তাহলে অবিলম্বে ব্যালেন্সিং অপারেশন শুরু হবে। সফল ব্যালেন্সিংয়ের পর মুনাফা গণনা করা হবে।
অবস্থা বার তথ্য
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
সিএনওয়াই-তে বিনিময় করার উদ্দেশ্য।
কোন মুদ্রায় রূপান্তর করতে, পাস করুনবর্তমান মুদ্রা থেকে লক্ষ্য মুদ্রায় বিনিময় হারথেকেSetRate
function.সম্পূর্ণ কৌশল:বিভিন্ন মুদ্রায় স্পট হেজিং কৌশল (টিউটোরিয়াল)