
কৌশল ডিজাইনে নতুনদের জন্য, হেজিং কৌশল একটি খুব ভাল অনুশীলন কৌশল। এই নিবন্ধটি একটি সহজ কিন্তু ব্যবহারিক ডিজিটাল মুদ্রা স্পট হেজিং কৌশল প্রয়োগ করে, আশা করছি যে নতুনরা ডিজাইনের কিছু অভিজ্ঞতা শিখতে পারবে।
প্রথমত, এটা স্পষ্ট যে যে কৌশলটি তৈরি করা হবে তা হল একটি ডিজিটাল মুদ্রা স্পট হেজিং কৌশল। আমরা সবচেয়ে সহজ হেজিং কৌশল তৈরি করি, যা হল দুটি স্পট এক্সচেঞ্জের মধ্যে উচ্চ মূল্যে এক্সচেঞ্জে বিক্রি করা এবং কম মূল্যে এক্সচেঞ্জে কেনা। লাভ করতে। পার্থক্যটা ধরো। যখন উচ্চ মূল্যের সকল বিনিময় মুদ্রায় (কারণ উচ্চ মূল্যের সকল মুদ্রা বিক্রি হয়) এবং কম মূল্যের সকল বিনিময় মুদ্রায় (কম মূল্যের সকল মুদ্রা কেনা হয়) থাকে, তখন হেজ করা অসম্ভব। এই সময়ে, আপনি কেবল দামের বিপরীত এবং হেজ হওয়ার জন্য অপেক্ষা করতে পারেন।
হেজিং করার সময়, অর্ডারের মূল্য এবং পরিমাণ রাখা হয়, এবং এক্সচেঞ্জের নির্ভুলতার সীমা থাকে এবং একটি ন্যূনতম অর্ডার সীমাও থাকে। ন্যূনতম সীমার পাশাপাশি, হেজিং করার সময় কৌশলটি অবশ্যই একটি হেজিংয়ের জন্য সর্বোচ্চ অর্ডার ভলিউম বিবেচনা করবে, যদি অর্ডারের পরিমাণ খুব বেশি হয়, তাহলে বাজারের জন্য পর্যাপ্ত অর্ডারের পরিমাণ থাকবে না। দুটি এক্সচেঞ্জের মুদ্রার মুদ্রা ভিন্ন হলে রূপান্তর করতে কীভাবে বিনিময় হার ব্যবহার করবেন তাও আপনাকে বিবেচনা করতে হবে। হেজিং, হ্যান্ডলিং ফি এবং অর্ডার নেওয়ার স্লিপেজ মানে এই নয় যে যতক্ষণ দামের পার্থক্য থাকে, হেজিং একটি ট্রিগার মানও থাকতে পারে যখন একটি নির্দিষ্ট মূল্যের চেয়ে কম হয় টাকা
এই বিবেচনার উপর ভিত্তি করে, কৌশলটি বিভিন্ন পরামিতি ডিজাইন করতে হবে:
hedgeDiffPrice, যখন মূল্য পার্থক্য এই মান অতিক্রম করে, হেজিং অপারেশন ট্রিগার করা হয়.minHedgeAmount, ন্যূনতম অর্ডারের পরিমাণ (কয়েনের সংখ্যা) যা হেজ করা যেতে পারে।maxHedgeAmount, একটি হেজের জন্য সর্বোচ্চ অর্ডারের পরিমাণ (কয়েনের সংখ্যা)।pricePrecisionA, বিনিময় A-এর অর্ডার মূল্য নির্ভুলতা (দশমিক স্থান)।amountPrecisionA, বিনিময় A-এর অর্ডার ভলিউম নির্ভুলতা (দশমিক স্থানের সংখ্যা)।pricePrecisionB, বিনিময় বি-তে অর্ডারের মূল্য নির্ভুলতা (দশমিক স্থানের সংখ্যা)।amountPrecisionB, এক্সচেঞ্জ B-এ অর্ডার ভলিউমের নির্ভুলতা (দশমিক স্থানের সংখ্যা)।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()
}
অবশেষে, আমরা ব্যালেন্স ফাংশনের ডিজাইন সম্পূর্ণ করতে এসেছি, যা একটু বেশি জটিল।
keepBalance
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
// 计算币差
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("无法平衡")
} else {
// 平衡下单
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("价格无效", price)
}
}
return false
} else if (!(initAccs.length == nowAccs.length && nowAccs.length == depths.length)) {
Log("错误:", "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]
এটি পরে কোড লিখতে খুব আরামদায়ক করে তুলবে।
// 精度,汇率设置
if (rateA != 1) {
// 设置汇率A
exA.SetRate(rateA)
Log("交易所A设置汇率:", rateA, "#FF0000")
}
if (rateB != 1) {
// 设置汇率B
exB.SetRate(rateB)
Log("交易所B设置汇率:", rateB, "#FF0000")
}
exA.SetPrecision(pricePrecisionA, amountPrecisionA)
exB.SetPrecision(pricePrecisionB, amountPrecisionB)
যদি বিনিময় হার পরামিতিrateA、rateBকিছু 1 এ সেট করা হয়েছে (ডিফল্ট হল 1), অর্থাৎrateA != 1বাrateB != 1ট্রিগার হবে না, তাই কোনও বিনিময় হার রূপান্তর সেট করা হবে না।

নীতিটি শুরু করার সময় কখনও কখনও সমস্ত লগ মুছে ফেলা এবং রেকর্ড করা ডেটা সাফ করা প্রয়োজন৷ আপনি একটি কৌশল ইন্টারফেস প্যারামিটার ডিজাইন করতে পারেনisReset, এবং তারপর কৌশলের প্রাথমিক অংশে রিসেট কোড ডিজাইন করুন, উদাহরণস্বরূপ:
if (isReset) { // 当isReset为真时重置数据
_G(null)
LogReset(1)
LogProfitReset()
LogVacuum()
Log("重置所有数据", "#FF0000")
}
nowAccsএই ভেরিয়েবলটি বর্তমান অ্যাকাউন্টের ডেটা রেকর্ড করতে ব্যবহৃত হয়, আমরা যে ফাংশনটি ডিজাইন করেছি তা ব্যবহার করেupdateAccsবর্তমান এক্সচেঞ্জের অ্যাকাউন্ট ডেটা পান।initAccsপ্রাথমিক অ্যাকাউন্টের স্থিতি রেকর্ড করতে ব্যবহৃত হয় (এ এবং বিনিময় বি এর কয়েনের সংখ্যা, মূল্যের কয়েনের সংখ্যা ইত্যাদি)। জন্যinitAccsপ্রথম ব্যবহার_G()ফাংশন পুনরুদ্ধার (_G ফাংশন অবিরামভাবে ডেটা রেকর্ড করে এবং রেকর্ড করা ডেটা ফেরত দিতে পারে বিস্তারিত জানার জন্য অনুগ্রহ করে এপিআই ডকুমেন্টেশন দেখুন:লিঙ্ক), যদি এটি জিজ্ঞাসা করা না যায়, তাহলে মান নির্ধারণ করতে এবং ব্যবহার করতে বর্তমান অ্যাকাউন্টের তথ্য ব্যবহার করুন_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
}
এখানে আপনি FMZ প্ল্যাটফর্ম ব্যবহার করে সমসাময়িক ফাংশন দেখতে পারেনexchange.Go, কলটি তৈরি করেছেনGetDepth()ইন্টারফেসের সামঞ্জস্য বস্তুdepthARoutine、depthBRoutine. যখন এই দুটি সমসাময়িক বস্তু তৈরি হয়, কল করুনGetDepth()ইন্টারফেসটিও অবিলম্বে ঘটেছিল এবং এই সময়ে এক্সচেঞ্জে গভীরতার ডেটা পাওয়ার জন্য দুটি অনুরোধ পাঠানো হয়েছিল।
এবং তারপর কলdepthARoutine、depthBRoutineবস্তুwait()গভীরতার তথ্য পাওয়ার পদ্ধতি।
গভীরতার তথ্য পাওয়ার পর, এর বৈধতা নির্ধারণের জন্য গভীরতার ডেটা পরীক্ষা করা দরকার। ডেটা অসঙ্গতি ঘটলে কার্যকরী ট্রিগার করুনcontinueবিবৃতি মূল লুপ পুনরায় কার্যকর করে।
价差值পরামিতি এখনও আছে差价比例প্যারামিটার? 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 এর পরামিতি একটি নির্দিষ্ট পরামিতির উপর ভিত্তি করে করা যেতে পারেপ্রদর্শনঅথবালুকান, যাতে আমরা ব্যবহার করতে হবে কিনা তা সিদ্ধান্ত নিতে একটি প্যারামিটার তৈরি করতে পারি价格差, এখনও差价比例。

কৌশল ইন্টারফেস প্যারামিটারে একটি প্যারামিটার যোগ করা হয়েছে।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 盘口条件满足
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("触发A->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, price, amount, nowAccs[1].Balance / price, nowAccs[0].Stocks) // 提示信息
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 盘口条件满足
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("触发B->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, price, amount, nowAccs[0].Balance / price, nowAccs[1].Stocks) // 提示信息
hedge(exA, exB, price, amount)
cancelAll()
lastKeepBalanceTS = 0
isTrade = true
}
}
বেশ কয়েকটি হেজিং ট্রিগার শর্ত রয়েছে:
1. হেজিং স্প্রেড প্রথমে পূরণ করতে হবে যখন দামের পার্থক্য সেট স্প্রেড প্যারামিটার পূরণ করে তখনই হেজিং করা যেতে পারে।
2. বাজারের হেজিং পরিমাণ অবশ্যই প্যারামিটারে সেট করা ন্যূনতম হেজিং পরিমাণ পূরণ করবে কারণ বিভিন্ন এক্সচেঞ্জের ন্যূনতম অর্ডার সীমা আলাদা হতে পারে, দুটির মধ্যে সবচেয়ে ছোটটি অবশ্যই নিতে হবে।
3. বিক্রির ক্রিয়াকলাপগুলির বিনিময়ে সম্পদগুলি বিক্রি করার জন্য যথেষ্ট, এবং কেনাকাটার ক্রিয়াকলাপের বিনিময়ে সম্পত্তিগুলি কেনার জন্য যথেষ্ট।
যখন এই শর্তগুলি পূরণ করা হয়, তখন হেজিং ফাংশনটি একটি হেজিং অর্ডার স্থাপনের জন্য কার্যকর করা হয়। প্রধান ফাংশনের আগে আমরা একটি ভেরিয়েবল আগেই ঘোষণা করেছিলাম।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
}
}
}
আপনি দেখতে পাচ্ছেন যে ব্যালেন্সিং ফাংশনটি নিয়মিতভাবে চালানো হয়, কিন্তু যদি হেজিং অপারেশনটি ট্রিগার করা হয়,lastKeepBalanceTS0 এ রিসেট করলে, ব্যালেন্সিং অপারেশন অবিলম্বে শুরু হবে। সফল ভারসাম্যের পরে সুবিধাগুলি গণনা করা হয়।
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",
"当前A,Stocks:", nowAccs[0].Stocks, "FrozenStocks:", nowAccs[0].FrozenStocks, "Balance:", nowAccs[0].Balance, "FrozenBalance", nowAccs[0].FrozenBalance, "\n",
"当前B,Stocks:", nowAccs[1].Stocks, "FrozenStocks:", nowAccs[1].FrozenStocks, "Balance:", nowAccs[1].Balance, "FrozenBalance", nowAccs[1].FrozenBalance, "\n",
"初始A,Stocks:", initAccs[0].Stocks, "FrozenStocks:", initAccs[0].FrozenStocks, "Balance:", initAccs[0].Balance, "FrozenBalance", initAccs[0].FrozenBalance, "\n",
"初始B,Stocks:", initAccs[1].Stocks, "FrozenStocks:", initAccs[1].FrozenStocks, "Balance:", initAccs[1].Balance, "FrozenBalance", initAccs[1].FrozenBalance)
স্ট্যাটাস বারটি ডিজাইনে বিশেষভাবে জটিল নয়, এটি বর্তমান সময়, বিনিময় A থেকে বিনিময় মূল্যের পার্থক্য এবং বিনিময় B থেকে A বিনিময় মূল্যের পার্থক্য প্রদর্শন করে। বর্তমান হেজিং টার্গেট স্প্রেড প্রদর্শন করে। বিনিময় A এর অ্যাকাউন্টের সম্পদের তথ্য এবং বিনিময় B এর অ্যাকাউন্টের সম্পদের ডেটা প্রদর্শন করুন।
প্যারামিটারের পরিপ্রেক্ষিতে, আমরা কৌশলের শুরুতে রূপান্তর বিনিময় হার মান পরামিতি ডিজাইন করেছিmainআমরা ফাংশনের প্রাথমিক অপারেশনের বিনিময় হার রূপান্তর অংশটিও ডিজাইন করেছি। এটা উল্লেখ করা উচিত যেSetRateবিনিময় হার রূপান্তর ফাংশন আগে নির্বাহ করা প্রয়োজন.
কারণ এই ফাংশন দুটি স্তরকে প্রভাবিত করে:
BTC_USDT, মূল্য একক সব হয়USDT, একাউন্টের সম্পদে উপলব্ধ মূল্যের মুদ্রাও রয়েছেUSDT. আমি যদি মানটিকে CNY তে রূপান্তর করতে চাই তবে কোডে সেট করুনexchange.SetRate(6.8)শুধুexchangeএই বিনিময় বস্তুর অধীনে সমস্ত ফাংশন দ্বারা প্রাপ্ত ডেটা CNY তে রূপান্তরিত হয়।
কেন রূপান্তরিত করার সময় মূল্যের মুদ্রা দেওয়া হয়?SetRateফাংশন পাসিংবর্তমান কোটেশন কারেন্সি থেকে টার্গেট কোটেশন কারেন্সিতে বিনিময় হার。সম্পূর্ণ কৌশল:বিভিন্ন ডিনোমিনেটেড মুদ্রার জন্য স্পট হেজিং কৌশল (টিউটোরিয়াল)