সাম্প্রতিককালে, এফএমজেড অফিসিয়াল গ্রুপে অনেকগুলি মার্টিনগেল-টাইপ কৌশল নিয়ে আলোচনা করা হয়েছে, এবং আমাদের প্ল্যাটফর্মে ক্রিপ্টোকারেন্সি চুক্তির অনেকগুলি মার্টিনগেল কৌশল নেই। অতএব, আমি একটি সহজ ক্রিপ্টোকারেন্সি ফিউচার মার্টিনগেল-টাইপ কৌশল ডিজাইন করার এই সুযোগটি গ্রহণ করেছি। কেন এটিকে মার্টিনগেল-টাইপ কৌশল বলা হয়? কারণ মার্টিনগেল কৌশলটির সম্ভাব্য ঝুঁকি প্রকৃতপক্ষে ছোট নয়, মার্টিনগেল কৌশল অনুসারে ডিজাইন করা দরকার নেই। তবে, এই ধরণের কৌশলগুলির এখনও প্রচুর ঝুঁকি রয়েছে এবং মার্টিনগেল-টাইপ কৌশলটির প্যারামিটার সেটিংস ঝুঁকির সাথে ঘনিষ্ঠভাবে সম্পর্কিত এবং ঝুঁকিগুলি উপেক্ষা করা উচিত নয়।
এই নিবন্ধে, আমরা প্রধানত মার্টিনগাল-টাইপ কৌশলগুলির নকশা থেকে ব্যাখ্যা এবং শিখি। কৌশল ধারণা নিজেই ইতিমধ্যে খুব স্পষ্ট, তাই আমরা, FMZ ব্যবহারকারী হিসাবে, কৌশল নকশা সম্পর্কে আরও বিবেচনা করতে পারেন।
মোট ইক্যুইটি প্রায়শই ক্রিপ্টোকারেন্সি ফিউচার কৌশল ডিজাইন করার সময় ব্যবহৃত হয়, কারণ আমরা মুনাফা গণনা করতে চাই, বিশেষত যখন আমাদের ভাসমান মুনাফা গণনা করতে হয়। যেহেতু হোল্ডিং পজিশন মার্জিন দখল করে, অপেক্ষমান অর্ডারগুলিও করে। সেই সময়ে, এপিআই ইন্টারফেসexchange.GetAccount()
এফএমজেড প্ল্যাটফর্মের উপলব্ধ সম্পদ এবং মুলতুবি অর্ডার হিমায়িত সম্পদ পেতে বলা হয়। প্রকৃতপক্ষে, বেশিরভাগ ক্রিপ্টোকারেন্সি ফিউচার প্ল্যাটফর্মগুলি মোট ইক্যুইটির ডেটা সরবরাহ করে, তবে এই সম্পত্তিটি এফএমজেডে অভিন্নভাবে প্যাকেজ করা হয় না।
অতএব, আমরা আলাদাভাবে বিভিন্ন প্ল্যাটফর্ম অনুযায়ী তথ্য পেতে ফাংশন ডিজাইনঃ
// OKEX V5 obtains the 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("Fail to obtain the total equity of the account!")
return null
}
}
return totalEquity
}
// Binance Ftures
function getTotalEquity_Binance() {
var totalEquity = null
var ret = exchange.GetAccount()
if (ret) {
try {
totalEquity = parseFloat(ret.Info.totalWalletBalance)
} catch(e) {
Log("Fail to obtain the total equity!")
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 "Do not support the platform"
}
}
মূল ফাংশন এবং মূল লজিক ডিজাইন করার আগে, আমাদের প্রস্তুতির জন্য কিছু সহায়ক ফাংশন ডিজাইন করতে হবে।
সমস্ত বর্তমান অপেক্ষমান অর্ডার বাতিল করুন
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)
}
ফিউচার ট্রেডিংয়ের জন্য চারটি দিক রয়েছেঃ খোলা লং পজিশন (openLong), খোলা শর্ট পজিশন (openShort), বন্ধ লং পজিশন (coverLong), এবং বন্ধ শর্ট পজিশন (coverShort) । অতএব, আমরা এই ক্রিয়াকলাপগুলির সাথে সামঞ্জস্যপূর্ণ চারটি অর্ডার ফাংশন ডিজাইন করেছি। যদি আপনি কেবল অর্ডার স্থাপন বিবেচনা করেন তবে বেশ কয়েকটি প্রয়োজনীয় কারণ রয়েছেঃ দিক, অর্ডার মূল্য এবং অর্ডার পরিমাণ।
আমরা একটি ফাংশনও ডিজাইন করেছি যার নাম:trade
যখন অপারেশন পরিচালনা করতেdirection (distance)
, order price (price)
এবংorder amount (amount)
নির্দিষ্ট করা হয়েছে।
খোলা লং পজিশন (openLong), খোলা শর্ট পজিশন (openShort), বন্ধ লং পজিশন (coverLong), এবং বন্ধ শর্ট পজিশন (coverShort) এর ফাংশন কল শেষ পর্যন্ত ফাংশন দ্বারা সম্পন্ন হয়trade
ফাংশন, অর্থাৎ, নির্দিষ্ট দিক, মূল্য এবং পরিমাণ অনুযায়ী, ফিউচার প্ল্যাটফর্মে অর্ডার স্থাপন।
কৌশল ধারণাটি খুব সহজ; বর্তমান মূল্যকে বেসলাইন হিসাবে নিন, এবং বেসলাইনের উপরে এবং নীচে একটি নির্দিষ্ট দূরত্ব থেকে বিক্রয় অর্ডার (শর্ট) এবং ক্রয় অর্ডার (লং) স্থাপন করুন। যদি এক পক্ষের অর্ডারগুলি কার্যকর করা হয়, তবে অবশিষ্ট সমস্ত অর্ডার বাতিল করুন, এবং তারপরে অবস্থান মূল্য অনুসারে একটি নির্দিষ্ট দূরত্বে নতুন ক্লোজ অর্ডার স্থাপন করা হবে, এবং ক্রয় অর্ডারগুলি আপডেট করা বর্তমান মূল্যে স্থাপন করা হবে, তবে ক্রয় অর্ডার অর্ডার পরিমাণ দ্বিগুণ হবে না।
প্রাথমিক কাজ আমরা যদি অর্ডারের জন্য অপেক্ষা করতে চাই, তাহলে আমাদের অর্ডার আইডি রেকর্ড করার জন্য দুটি ভেরিয়েবলের প্রয়োজন।
var buyOrderId = null
var sellOrderId = null
তারপরে, OKEX_V5 সিমুলেটেড বট ব্যবহারের বিকল্পটি কৌশল ইন্টারফেসের পরামিতিগুলিতে ডিজাইন করা হয়েছে, তাই কিছু প্রক্রিয়াকরণ কোডে করা দরকারঃ
var exName = exchange.GetName()
// switch to 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 percision", pricePrecision, amountPrecision)
নকশা মধ্যে সহজ তথ্য পুনরুদ্ধার ফাংশন
if (totalEq == -1 && !IsVirtual()) {
var recoverTotalEq = _G("totalEq")
if (!recoverTotalEq) {
var currTotalEq = getTotalEquity()
if (currTotalEq) {
totalEq = currTotalEq
_G("totalEq", currTotalEq)
} else {
throw "Fail to obtain the 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, in which we mainly use the latest trading price
var pos = _C(exchange.GetPosition) // read the current position data
if (pos.length > 1) { // judge the position data; due to the strategy logic, it is unlikely to have long and short positions at the same time, so if there are long and short positions at the same time, an error will be thrown
Log(pos)
throw "concurrently with long and short positions" // raise an error, and stop the strategy
}
// according to the status
if (pos.length == 0) { // according to the position status, make different operations; if pos.length == 0, it means currently no position
// when there is no position yet, calculate the equity
if (!IsVirtual()) {
var currTotalEq = getTotalEquity()
if (currTotalEq) {
LogProfit(currTotalEq - totalEq, "Current total equity:", currTotalEq)
}
}
buyOrderId = openLong(ticker.Last - targetProfit, amount) // pend buy order of open long position
sellOrderId = openShort(ticker.Last + targetProfit, amount) // pend sell order of open short position
} else if (pos[0].Type == PD_LONG) { // there are long positions; pending position and amount are
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) { // there are short positions; pending position and amount 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 opending orders of one side fails, cancel all pending orders and try again
cancelAll()
buyOrderId = null
sellOrderId = null
continue
}
while (1) { // finish pending the order, and start to monitor 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) { // both buy order and sell order are detected to be executed
cancelAll()
break
} else if (!isFindBuyId) { // a buy order execution is detected
Log("buy order executed")
cancelAll()
break
} else if (!isFindSellId) { // a sell order execution is detected
Log("sell order executed")
cancelAll()
break
}
LogStatus(_D())
Sleep(3000)
}
Sleep(500)
}
তখন পুরো যুক্তি এবং নকশা সম্পূর্ণরূপে ব্যাখ্যা করা হয়।
২০২১ সালের ১৯ মে বাজারের কোটেশনগুলোতে এই কৌশলটি দেখানো হোক।
যেমনটি আমরা দেখতে পাচ্ছি, মার্টিনগেল কৌশল অনুরূপ কৌশল এখনও কিছু ঝুঁকি আছে।
কৌশল ঠিকানাঃhttps://www.fmz.com/strategy/294957
কৌশলটি মূলত অধ্যয়নের জন্য ব্যবহৃত হয়, তাই কৌশলটি একটি বাস্তব বটে ব্যবহার করবেন না!