ট্রেডিং ভিউ ব্যবহার করে এমন ব্যবসায়ীরা জানেন যে ট্রেডিং ভিউ অন্যান্য প্ল্যাটফর্মগুলিতে বার্তা প্রেরণ করতে পারে। আমাদের
এই নিবন্ধের শিরোনাম এবং উপরের বর্ণনা কিছু নতুনদের বিভ্রান্ত করতে পারে, এটি কোন ব্যাপার না! আসুন চাহিদা দৃশ্যকল্প এবং নীতিগুলির একটি পরিষ্কার বর্ণনা দিয়ে শুরু করি। ঠিক আছে, আসুন এখানে বিষয়টিতে যাই।
চাহিদার দৃশ্যকল্পঃ সুতরাং আমরা এটি কী ধরণের কাজ করতে চাই? সহজভাবে বলতে গেলে, আমাদের কাছে প্রচুর সূচক, কৌশল, কোড ইত্যাদি রয়েছে যা আমরা ট্রেডিংভিউতে ব্যবহার করতে পারি, যা ট্রেডিংভিউতে সরাসরি লাইন আঁকতে, গণনা করতে এবং ট্রেডিং সিগন্যাল প্রদর্শন করতে চালানো যেতে পারে। এছাড়াও, ট্রেডিংভিউতে রিয়েল-টাইম মূল্যের ডেটা এবং বিভিন্ন সূচক গণনা সহজ করার জন্য পর্যাপ্ত কে-লাইন ডেটা রয়েছে। ট্রেডিংভিউতে এই স্ক্রিপ্ট কোডগুলিকে পাইন ভাষা বলা হয়। একমাত্র জিনিসটি সুবিধাজনক নয় যে ট্রেডিংভিউতে আসল বট ট্রেডিং। যদিও পাইন ভাষাটি এফএমজেডে সমর্থিত, এটি আসল বট ট্রেডিংয়ের জন্যও ব্যবহার করা যেতে পারে। তবে কিছু ট্রেডিংভিউ অনুরাগী এখনও ট্রেডিংভিউতে চার্ট থেকে সংকেত ব্যবহার করে অর্ডার দিতে চান, তাই এটি এফএমজেড দ্বারা সমাধান করা যেতে পারে। সুতরাং এই নিবন্ধে, আমরা সমাধানের বিশদ ব্যাখ্যা করব।
নীতিঃ
সমগ্র কর্মসূচিতে চারটি বিষয় জড়িত রয়েছে, যা সংক্ষেপে নিম্নরূপঃ
সুতরাং যদি আপনি এটি এই ভাবে ব্যবহার করতে চান, আপনার এই প্রস্তুতি প্রয়োজনঃ
পূর্ববর্তী সংস্করণে
তারপর ট্রেডিংভিউ ফাইগারে প্রদর্শিত হিসাবে সেট করা যেতে পারে অনুরোধ শরীরের মধ্যে বার্তা লিখতে এবং FMZ এর বর্ধিত API ইন্টারফেসে পাঠাতে। কিভাবে FMZ এর বর্ধিত API ইন্টারফেস কল করবেন?
এফএমজেডের বিস্তৃত এপিআই ইন্টারফেসের একটি সিরিজে, আমাদেরCommandRobot
ইন্টারফেস, যা সাধারণত নিম্নরূপ বলা হয়ঃ
https://www.fmz.com/api/v1?access_key=xxx&secret_key=yyyy&method=CommandRobot&args=[186515,"ok12345"]
দ্যaccess_key
এবংsecret_key
মধ্যেquery
এই অনুরোধের url হল প্রসারিতAPI KEY
FMZ প্ল্যাটফর্ম, এখানে ডেমো সেটxxx
এবংyyyy
. তাহলে কিভাবে এই কী তৈরি করবেন? এই পৃষ্ঠায়ঃhttps://www.fmz.com/m/account
, এটি তৈরি করুন, এটি যথাযথভাবে রাখুন, এটি প্রকাশ করবেন না।
ফিরে পয়েন্ট, এর ইন্টারফেস সমস্যা সম্পর্কে কথা বলতে চলুনCommandRobot
. যদি আপনি অ্যাক্সেস প্রয়োজনCommandRobot
ইন্টারফেস,method
অনুরোধে সেট করা হবেঃCommandRobot
.CommandRobot
ইন্টারফেস একটি ইন্টারেক্টিভ বার্তা পাঠাতে হয় একটি বাস্তব বট একটি আইডি সঙ্গে FMZ প্ল্যাটফর্মের মাধ্যমে, তাই প্যারামিটারargs
প্রকৃত বট আইডি এবং বার্তা ধারণ করে। উপরের অনুরোধ url উদাহরণ বার্তা পাঠাতে হয়ok12345
একটা আসল বট প্রোগ্রামের সাথে যার আইডি ১৮৬৫১৫।
পূর্বে, এই পদ্ধতিটি FMZ বর্ধিত API এর CommandRobot ইন্টারফেসের অনুরোধ করতে ব্যবহৃত হয়। বার্তাগুলি কেবল উপরের উদাহরণে লেখা যেতে পারে, যেমনok12345
. যদি বার্তাটি অনুরোধকৃত বডিতে থাকে, তাহলে আপনাকে অন্য পদ্ধতি ব্যবহার করতে হবেঃ
https://www.fmz.com/api/v1?access_key=xxx&secret_key=yyyy&method=CommandRobot&args=[130350,+""]
এই ভাবে, অনুরোধটি আইডি সহ বাস্তব বটকে একটি ইন্টারেক্টিভ বার্তা হিসাবে অনুরোধের মধ্যে শরীরের সামগ্রী পাঠাতে পারে130350
FMZ প্ল্যাটফর্মের মাধ্যমে। যদি ট্রেডিং ভিউতে বার্তাটি সেট করা থাকেঃ{"close": {{close}}, "name": "aaa"}
, তাহলে আসল বট যার আইডি130350
ইন্টারেক্টিভ নির্দেশনা পাবেন:{"close": 39773.75, "name": "aaa"}
{
Flag: "45M103Buy", // Marker, which can be specified at will
Exchange: 1, // Specify exchange trading pairs
Currency: "BTC_USDT", // Trading pair
ContractType: "swap", // Contract type, swap, quarter, next_quarter, fill in spot for spot
Price: "{{close}}", // Opening position or closing position price, -1 is the market price
Action: "buy", // Transaction type [buy: spot buying, sell: spot selling, long: go long futures, short: go short futures, closesell: buy futures and close short positions, close buy: sell futures and close long positions]
Amount: "0", // Transaction amount
}
কৌশলটি একটি মাল্টি-এক্সচেঞ্জ আর্কিটেকচার হিসাবে ডিজাইন করা হয়েছে, তাই একাধিক এক্সচেঞ্জ অবজেক্ট এই কৌশলটিতে কনফিগার করা যেতে পারে, অর্থাৎ, একাধিক বিভিন্ন অ্যাকাউন্টের অর্ডার স্থাপন অপারেশন নিয়ন্ত্রণ করা যেতে পারে। কেবলমাত্র সিগন্যাল কাঠামোর এক্সচেঞ্জটি পরিচালনা করার জন্য এক্সচেঞ্জটি নির্দিষ্ট করে। 1 সেটিংটি এই সংকেতটিকে প্রথম যুক্ত এক্সচেঞ্জ অবজেক্টের সাথে সামঞ্জস্যপূর্ণ এক্সচেঞ্জ অ্যাকাউন্টটি পরিচালনা করতে সক্ষম করতে হবে। যদি স্পট কন্ট্রাক্ট টাইপ স্পট সেট করা থাকে তবে ফিউচারগুলি নির্দিষ্ট চুক্তি লিখবে, যেমন, চিরস্থায়ী চুক্তির জন্য স্যুপ। বাজার মূল্য তালিকাটি -1-এ পাস করা যেতে পারে। ফিউচার, স্পট, খোলার এবং বন্ধের অবস্থানের জন্য অ্যাকশন সেটিংস আলাদা এবং এটি ভুলভাবে সেট করা যায় না।
পরবর্তী, আপনি কৌশল কোড ডিজাইন করতে পারেন. সম্পূর্ণ কৌশল কোডঃ
//Signal structure
var Template = {
Flag: "45M103Buy", // Marker, which can be specified at will
Exchange: 1, // Specify exchange trading pairs
Currency: "BTC_USDT", // Trading pair
ContractType: "swap", // Contract type, swap, quarter, next_quarter, fill in spot for spot
Price: "{{close}}", // Opening position or closing position price, -1 is the market price
Action: "buy", // Transaction type [buy: spot buying, sell: spot selling, long: go long futures, short: go short futures, closesell: buy futures and close short positions, close buy: sell futures and close long positions]
Amount: "0", // Transaction amount
}
var BaseUrl = "https://www.fmz.com/api/v1" // FMZ extended API interface address
var RobotId = _G() // Current real bot ID
var Success = "#5cb85c" // Color for success
var Danger = "#ff0000" // Color for danger
var Warning = "#f0ad4e" // Color for alert
var buffSignal = []
// Check signal message format
function DiffObject(object1, object2) {
const keys1 = Object.keys(object1)
const keys2 = Object.keys(object2)
if (keys1.length !== keys2.length) {
return false
}
for (let i = 0; i < keys1.length; i++) {
if (keys1[i] !== keys2[i]) {
return false
}
}
return true
}
function CheckSignal(Signal) {
Signal.Price = parseFloat(Signal.Price)
Signal.Amount = parseFloat(Signal.Amount)
if (Signal.Exchange <= 0 || !Number.isInteger(Signal.Exchange)) {
Log("The minimum number of the exchange is 1 and it is an integer", Danger)
return
}
if (Signal.Amount <= 0 || typeof(Signal.Amount) != "number") {
Log("The transaction amount cannot be less than 0 and it is numerical type", typeof(Signal.Amount), Danger)
return
}
if (typeof(Signal.Price) != "number") {
Log("Price must be a value", Danger)
return
}
if (Signal.ContractType == "spot" && Signal.Action != "buy" && Signal.Action != "sell") {
Log("The command is to operate spot, Action error, Action:", Signal.Action, Danger)
return
}
if (Signal.ContractType != "spot" && Signal.Action != "long" && Signal.Action != "short" && Signal.Action != "closesell" && Signal.Action != "closebuy") {
Log("The command is to operate future, Action error, Action:", Signal.Action, Danger)
return
}
return true
}
function commandRobot(url, accessKey, secretKey, robotId, cmd) {
// https://www.fmz.com/api/v1?access_key=xxx&secret_key=xxx&method=CommandRobot&args=[xxx,+""]
url = url + '?access_key=' + accessKey + '&secret_key=' + secretKey + '&method=CommandRobot&args=[' + robotId + ',+""]'
var postData = {
method:'POST',
data:cmd
}
var headers = "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36\nContent-Type: application/json"
var ret = HttpQuery(url, postData, "", headers)
Log("Simulate a webhook request from TradingView, sending a POST request for testing purposes:", url, "body:", cmd, "response:", ret)
}
function createManager() {
var self = {}
self.tasks = []
self.process = function() {
var processed = 0
if (self.tasks.length > 0) {
_.each(self.tasks, function(task) {
if (!task.finished) {
processed++
self.pollTask(task)
}
})
if (processed == 0) {
self.tasks = []
}
}
}
self.newTask = function(signal) {
// {"Flag":"45M103Buy","Exchange":1,"Currency":"BTC_USDT","ContractType":"swap","Price":"10000","Action":"buy","Amount":"0"}
var task = {}
task.Flag = signal["Flag"]
task.Exchange = signal["Exchange"]
task.Currency = signal["Currency"]
task.ContractType = signal["ContractType"]
task.Price = signal["Price"]
task.Action = signal["Action"]
task.Amount = signal["Amount"]
task.exchangeIdx = signal["Exchange"] - 1
task.pricePrecision = null
task.amountPrecision = null
task.error = null
task.exchangeLabel = exchanges[task.exchangeIdx].GetLabel()
task.finished = false
Log("Create task:", task)
self.tasks.push(task)
}
self.getPrecision = function(n) {
var precision = null
var arr = n.toString().split(".")
if (arr.length == 1) {
precision = 0
} else if (arr.length == 2) {
precision = arr[1].length
}
return precision
}
self.pollTask = function(task) {
var e = exchanges[task.exchangeIdx]
var name = e.GetName()
var isFutures = true
e.SetCurrency(task.Currency)
if (task.ContractType != "spot" && name.indexOf("Futures_") != -1) {
// Non-spot, then set the contract
e.SetContractType(task.ContractType)
} else if (task.ContractType == "spot" && name.indexOf("Futures_") == -1) {
isFutures = false
} else {
task.error = "The ContractType in the command does not match the configured exchange object type"
return
}
var depth = e.GetDepth()
if (!depth || !depth.Bids || !depth.Asks) {
task.error = "Order book data exception"
return
}
if (depth.Bids.length == 0 && depth.Asks.length == 0) {
task.error = "No orders on the market entry position"
return
}
_.each([depth.Bids, depth.Asks], function(arr) {
_.each(arr, function(order) {
var pricePrecision = self.getPrecision(order.Price)
var amountPrecision = self.getPrecision(order.Amount)
if (Number.isInteger(pricePrecision) && !Number.isInteger(self.pricePrecision)) {
self.pricePrecision = pricePrecision
} else if (Number.isInteger(self.pricePrecision) && Number.isInteger(pricePrecision) && pricePrecision > self.pricePrecision) {
self.pricePrecision = pricePrecision
}
if (Number.isInteger(amountPrecision) && !Number.isInteger(self.amountPrecision)) {
self.amountPrecision = amountPrecision
} else if (Number.isInteger(self.amountPrecision) && Number.isInteger(amountPrecision) && amountPrecision > self.amountPrecision) {
self.amountPrecision = amountPrecision
}
})
})
if (!Number.isInteger(self.pricePrecision) || !Number.isInteger(self.amountPrecision)) {
task.err = "Failed to obtain precision"
return
}
e.SetPrecision(self.pricePrecision, self.amountPrecision)
// buy: spot buying, sell: spot selling, long: go long futures, short: go short futures, closesell: buy futures and close short positions, close buy: sell futures and close long positions
var direction = null
var tradeFunc = null
if (isFutures) {
switch (task.Action) {
case "long":
direction = "buy"
tradeFunc = e.Buy
break
case "short":
direction = "sell"
tradeFunc = e.Sell
break
case "closesell":
direction = "closesell"
tradeFunc = e.Buy
break
case "closebuy":
direction = "closebuy"
tradeFunc = e.Sell
break
}
if (!direction || !tradeFunc) {
task.error = "Wrong transaction direction:" + task.Action
return
}
e.SetDirection(direction)
} else {
if (task.Action == "buy") {
tradeFunc = e.Buy
} else if (task.Action == "sell") {
tradeFunc = e.Sell
} else {
task.error = "Wrong transaction direction:" + task.Action
return
}
}
var id = tradeFunc(task.Price, task.Amount)
if (!id) {
task.error = "Failed to place an order"
}
task.finished = true
}
return self
}
var manager = createManager()
function HandleCommand(signal) {
// Detect whether interactive command is received
if (signal) {
Log("Receive interactive command:", signal) // Receive the interactive command, print the interactive command
} else {
return // If it is not received, it will be returned directly without processing
}
// Check whether the interactive command is a test instruction. The test instruction can be sent out by the current strategy interaction control for testing
if (signal.indexOf("TestSignal") != -1) {
signal = signal.replace("TestSignal:", "")
// Call the FMZ extended API interface to simulate the webhook of the TradingView, and the message sent by the interactive button TestSignal: {"Flag":"45M103Buy","Exchange":1,"Currency":"BTC_USDT","ContractType":"swap","Price":"10000","Action":"buy","Amount":"0"}
commandRobot(BaseUrl, FMZ_AccessKey, FMZ_SecretKey, RobotId, signal)
} else if (signal.indexOf("evalCode") != -1) {
var js = signal.split(':', 2)[1]
Log("Execute debug code:", js)
eval(js)
} else {
// Process signal command
objSignal = JSON.parse(signal)
if (DiffObject(Template, objSignal)) {
Log("Received transaction signal command:", objSignal)
buffSignal.push(objSignal)
// Check the trading volume and exchange number
if (!CheckSignal(objSignal)) {
return
}
// Create task
manager.newTask(objSignal)
} else {
Log("Command cannot be recognized", signal)
}
}
}
function main() {
Log("WebHook address:", "https://www.fmz.com/api/v1?access_key=" + FMZ_AccessKey + "&secret_key=" + FMZ_SecretKey + "&method=CommandRobot&args=[" + RobotId + ',+""]', Danger)
Log("Transaction type [buy: spot buying, sell: spot selling, long: go long futures, short: go short futures, closesell: buy futures and close short positions, close buy: sell futures and close long positions]", Danger)
Log("Command template:", JSON.stringify(Template), Danger)
while (true) {
try {
// Process interactions
HandleCommand(GetCommand())
// Process tasks
manager.process()
if (buffSignal.length > maxBuffSignalRowDisplay) {
buffSignal.shift()
}
var buffSignalTbl = {
"type" : "table",
"title" : "Signal recording",
"cols" : ["Flag", "Exchange", "Currency", "ContractType", "Price", "Action", "Amount"],
"rows" : []
}
for (var i = buffSignal.length - 1 ; i >= 0 ; i--) {
buffSignalTbl.rows.push([buffSignal[i].Flag, buffSignal[i].Exchange, buffSignal[i].Currency, buffSignal[i].ContractType, buffSignal[i].Price, buffSignal[i].Action, buffSignal[i].Amount])
}
LogStatus(_D(), "\n", "`" + JSON.stringify(buffSignalTbl) + "`")
Sleep(1000 * SleepInterval)
} catch (error) {
Log("e.name:", error.name, "e.stack:", error.stack, "e.message:", error.message)
Sleep(1000 * 10)
}
}
}
কৌশলগত পরামিতি এবং মিথস্ক্রিয়াঃ
কৌশলটি চালানোর আগে, এক্সচেঞ্জ অবজেক্টটি কনফিগার করা উচিত, এবং দুটি পরামিতি
এটি ওয়েবহুক ঠিকানা, সমর্থিত অ্যাকশন কমান্ড এবং বার্তা বিন্যাস যা ট্রেডিংভিউতে পূরণ করতে হবে তা মুদ্রণ করবে। গুরুত্বপূর্ণ বিষয় হল ওয়েবহুক ঠিকানাঃ
https://www.fmz.com/api/v1?access_key=22903bab96b26584dc5a22522984df42&secret_key=73f8ba01014023117cbd30cb9d849bfc&method=CommandRobot&args=[505628,+""]
শুধু কপি করে সরাসরি ট্রেডিং ভিউ-এর সংশ্লিষ্ট স্থানে পেস্ট করুন।
আপনি যদি ট্রেডিং ভিউ দ্বারা প্রেরিত একটি সংকেত সিমুলেট করতে চান, আপনি কৌশল মিথস্ক্রিয়া উপর টেস্টসিগন্যাল বোতামে ক্লিক করতে পারেন।
এই কৌশলটি নিজস্ব একটি অনুরোধ পাঠায় (একটি ট্রেডিং ভিউকে সিমুলেট করে যা একটি সংকেত অনুরোধ পাঠায়), কৌশলটিকে নিজেই একটি বার্তা পাঠাতে FMZ
{"Flag":"45M103Buy","Exchange":1,"Currency":"BTC_USDT","ContractType":"swap","Price":"16000","Action":"buy","Amount":"1"}
বর্তমান কৌশলটি আরেকটি ইন্টারেক্টিভ বার্তা পাবেন এবং কার্যকর, এবং লেনদেনের জন্য একটি অর্ডার স্থাপন.
ট্রেডিংভিউ টেস্ট ব্যবহার করার জন্য ট্রেডিংভিউ অ্যাকাউন্টটি প্রো স্তরে থাকা প্রয়োজন। টেস্টের আগে, আপনাকে কিছু পূর্ব জ্ঞান থাকতে হবে।
উদাহরণস্বরূপ একটি সহজ পাইন স্ক্রিপ্ট নিন (এলোমেলোভাবে ট্রেডিংভিউতে পাওয়া এবং পরিবর্তিত)
//@version=5
strategy("Consecutive Up/Down Strategy", overlay=true)
consecutiveBarsUp = input(3)
consecutiveBarsDown = input(3)
price = close
ups = 0.0
ups := price > price[1] ? nz(ups[1]) + 1 : 0
dns = 0.0
dns := price < price[1] ? nz(dns[1]) + 1 : 0
if (not barstate.ishistory and ups >= consecutiveBarsUp and strategy.position_size <= 0)
action = strategy.position_size < 0 ? "closesell" : "long"
strategy.order("ConsUpLE", strategy.long, 1, comment=action)
if (not barstate.ishistory and dns >= consecutiveBarsDown and strategy.position_size >= 0)
action = strategy.position_size > 0 ? "closebuy" : "short"
strategy.order("ConsDnSE", strategy.short, 1, comment=action)
নিম্নলিখিত স্থানধারক হয়. উদাহরণস্বরূপ, যদি আমি লিখতে{{strategy.order.contracts}}
সতর্কতার
{{strategy.position_size}}
- পাইনে একই কীওয়ার্ডের মান ফেরত দিন, অর্থাৎ বর্তমান অবস্থানের আকার।{{strategy.order.action}}
- এক্সিকিউটেড অর্ডারের জন্য {{strategy.order.contracts}}
- অর্ডার কার্যকর করা হয়েছে যে চুক্তির সংখ্যা ফেরত।{{strategy.order.price}}
- কার্যকর আদেশের মূল্য ফেরত দিন।{{strategy.order.id}}
- এক্সিকিউটেড অর্ডারের আইডি ফেরত দিন (অর্ডার তৈরি করে এমন ফাংশন কলগুলির মধ্যে একটিতে প্রথম প্যারামিটার হিসাবে ব্যবহৃত স্ট্রিংঃ strategy.entry,strategy.exitঅথবা কৌশল.অর্ডার) ।{{strategy.order.comment}}
- এক্সিকিউটেড অর্ডারের মন্তব্য ফেরত দিন (অর্ডার তৈরি করে এমন ফাংশন কলগুলির মধ্যে একটিতে মন্তব্য প্যারামিটারে ব্যবহৃত স্ট্রিংঃ strategy.entry,strategy.exit, অথবা strategy.order) যদি কোন মন্তব্য নির্দিষ্ট করা হয় না, মানstrategy.order.idব্যবহার করা হবে।{{strategy.order.alert_message}}
- alert_message প্যারামিটারের মান প্রদান করে যা strategy{{strategy.market_position}}
- স্ট্র্যাটেজির বর্তমান অবস্থানকে স্ট্রিং হিসেবে ফেরত দিনঃ {{strategy.market_position_size}}
- বর্তমান অবস্থানের আকারকে একটি পরম মান (অর্থাত্, একটি অ-নেতিবাচক সংখ্যা) আকারে প্রদান করে।{{strategy.prev_market_position}}
- স্ট্র্যাটেজির পূর্ববর্তী অবস্থানটি স্ট্রিং হিসাবে ফেরত দিনঃ {{strategy.prev_market_position_size}}
- একটি পরম মান (যেমন, একটি অ-নেতিবাচক সংখ্যা) আকারে পূর্ববর্তী অবস্থানের আকার ফেরত দেয়।
{
"Flag":"{{strategy.order.id}}",
"Exchange":1,
"Currency":"BTC_USDT",
"ContractType":"swap",
"Price":"-1",
"Action":"{{strategy.order.comment}}",
"Amount":"{{strategy.order.contracts}}"
}
যখন ট্রেডিং ভিউতে PINE স্ক্রিপ্টটি একটি লেনদেনকে ট্রিগার করে, তখন একটি ওয়েবহুক url অনুরোধ পাঠানো হবে।
এফএমজেডের আসল বট এই সিগন্যালটি চালাবে।
এই নিবন্ধে কোডটি শুধুমাত্র রেফারেন্সের জন্য এবং আপনি এটিকে নিজের দ্বারা ব্যবহারের সময় সামঞ্জস্য এবং সম্প্রসারণ করতে পারেন।