یہ حکمت عملی ایک ایسی حکمت عملی ہے جو بہت پہلے ڈیجیٹل کرنسی 796 فیوچر ایکسچینج پر لاگو کی گئی تھی۔ فیوچر معاہدے کرنسی پر مبنی ہیں ، یعنی ، مارجن کو کرنسی کے لحاظ سے کم کیا جاتا ہے (مثال کے طور پر ، بی ٹی سی معاہدوں کو بی ٹی سی سے کم کیا جاتا ہے) ۔ معاہدوں کی آرڈر کی مقدار اعشاریہ ہوسکتی ہے ، جو بائننس کے کرنسی پر مبنی معاہدوں کی طرح ہے۔ حکمت عملی سیکھنے کی حکمت عملی ڈیزائن کے لئے استعمال کیا جاتا ہے، منطق پروسیسنگ اب بھی بہت اچھا ہے، اور حکمت عملی بنیادی طور پر سیکھنے کے لئے استعمال کیا جاتا ہے.
حکمت عملی کوڈ نوٹس
var FirstTradeType = [ORDER_TYPE_BUY, ORDER_TYPE_SELL][OpType]; // The first opening position direction is determined according to the parameter OpType opening position direction. The value of the global variable FirstTradeType is ORDER_ TYPE_ BUY or ORDER_ TYPE_ SELL
var OrgAccount = null; // Global variable, recording account assets
var Counter = {s : 0, f: 0}; // Declare a variable Counter, the value is initialized to an object (a similar structure python named dictionary), s represents the number of win time, f represents the number of losses
var LastProfit = 0; // Recent P&L
var AllProfit = 0; // Total P&L
var _Failed = 0; // Number of stop-losses
// Cancel all orders other than those with an ID in the list of pending orders. If the orderId parameter was not passed in, cancel all pending orders of the current trading pair. The parameter e is the reference of the exchange object. For example, when exchange is passed in as a parameter, e is the alias of exchange
function StripOrders(e, orderId) {
var order = null; // Initialize the variable order to null
if (typeof(orderId) == 'undefined') { // If the parameter orderId is not written when it is passed in, then typeof (orderId)=='undefined' holds, the code block of the if statement is executed, and the orderId is assigned to null
orderId = null;
}
while (true) { // Process loop
var dropped = 0; // Process number of markers
var orders = _C(e.GetOrders); // Call GetOrders to get the current pending orders (orders that are not dealt) and assign the value to orders
for (var i = 0; i < orders.length; i++) { // Traverse the list of outstanding orders
if (orders[i].Id == orderId) { // If the order ID is the same as the order ID passed in the parameter, assign the value orders[i] to the local variable order in the function. Orders [i] refers to the current order structure when traversing
order = orders[i];
} else { // If the IDs are not the same, perform revocation
var extra = ""; // Set the extension information extra according to the partial deals
if (orders[i].DealAmount > 0) {
extra = "Deal:" + orders[i].DealAmount;
} else {
extra = "Unsettled";
}
e.SetDirection(orders[i].Type == ORDER_TYPE_BUY ? "buy" : "sell");
e.CancelOrder(orders[i].Id, orders[i].Type == ORDER_TYPE_BUY ? "purchase order" : "selling order", extra); // Cancel the order, with extra information output, which will be displayed in the log
dropped++; // dropped count accumulation
}
}
if (dropped == 0) { // When the traversal is completed, dropped is equal to 0, that is, there is no cancellation during traversal (there is no order to be canceled), that is, the cancellation processing is completed, and the while loop is skipped
break;
}
Sleep(300); // Prevent the rotation frequency from being too fast, with a certain interval each time
}
return order; // Return the order to find
}
var preMsg = ""; // Variables for recording cache information
function GetAccount(e, waitFrozen) { // Obtain the account asset information. The parameter e is also a reference to exchange. The parameter waitFrozen controls whether to wait for freezing
if (typeof(waitFrozen) == 'undefined') { // If the waitFrozen parameter is not passed in during the call, the parameter waitFrozen is assigned a value of false, that is, the default is not to wait for freezing
waitFrozen = false;
}
var account = null;
var alreadyAlert = false; // Mark if the variable has been alerted
while (true) { // Get the current account information and detect freezing. If you do not wait for freezing, it will skip the while loop directly
account = _C(e.GetAccount);
if (!waitFrozen || account.FrozenStocks < MinStock) {
break;
}
if (!alreadyAlert) {
alreadyAlert = true; // Once the reminder is triggered, the alreadyAlert will be reset to avoid repeated reminders
Log("find frozen money or currencies in the account", account); // Output reminder log
}
Sleep(Interval);
}
msg = "successful:" + Counter.s + "times, failed:" + Counter.f + "times, current account currencies: " + account.Stocks;
if (account.FrozenStocks > 0) {
msg += "frozen currencies:" + account.FrozenStocks;
}
if (msg != preMsg) { // Check if the current message is different from the last one, and update it on the status bar if it is different
preMsg = msg;
LogStatus(msg, "#ff0000");
}
return account; // Function returns to account structure of the account information
}
function GetPosition(e, orderType) { // Get the position, or get the position in the specified direction
var positions = _C(e.GetPosition); // Get the position
if (typeof(orderType) == 'undefined') { // The orderType parameter is the position type speicfied to be obtained. If no orderType parameter is passed in, all positions will be returned directly
return positions;
}
for (var i = 0; i < positions.length; i++) { // Traverse the list of positions
if (positions[i].Type == orderType) { // If the current traversed position data is the direction to be found (orderType)
return positions[i]; // Return to the position of orderType
}
}
return null;
}
function GetTicker(e) { // Get ticker market data
while (true) {
var ticker = _C(e.GetTicker); // Get ticker market information
if (ticker.Buy > 0 && ticker.Sell > 0 && ticker.Sell > ticker.Buy) { // Check the reliability of the market data
return ticker; // Return to ticker data
}
Sleep(100);
}
}
// mode = 0 : direct buy, 1 : buy as buy1
function Trade(e, tradeType, tradeAmount, mode, slidePrice, maxSpace, retryDelay) { // Trading functions
// e Exchange object reference, trading direction of tradeType (buy/sell), trading volume of tradeAmount, the trading mode is mode, slidePrice means slide price, maxSpace means maximum distance of pending order, retryDelay means retry intervals
var initPosition = GetPosition(e, tradeType); // Get the position data of the specified direction, name it as initPosition
var nowPosition = initPosition; // Declare another variable, nowPosition, and assign it with initPosition
var orderId = null;
var prePrice = 0; // The price of placing order at last loop
var dealAmount = 0; // Number of transactions already made
var diffMoney = 0;
var isFirst = true; // The marker of first loop execution
var tradeFunc = tradeType == ORDER_TYPE_BUY ? e.Buy : e.Sell; // Function for placing orders, and call e.Buy or e.Sell according to the parameter tradeType
var isBuy = tradeType == ORDER_TYPE_BUY; // Marker for buying
while (true) { // while loop
var account = _C(e.GetAccount); // Obtain the current account asset data
var ticker = GetTicker(e); // Obtain the current market data
var tradePrice = 0; // Set transaction prices based on mode parameters
if (isBuy) {
tradePrice = _N((mode == 0 ? ticker.Sell : ticker.Buy) + slidePrice, 4);
} else {
tradePrice = _N((mode == 0 ? ticker.Buy : ticker.Sell) - slidePrice, 4);
}
if (orderId == null) {
if (isFirst) { // Judge according to the isFirst marker variable, if it is the first execution, do nothing
isFirst = false; // Set the isFirst marker as false, indicating that it was not executed for the first time
} else { // Non-first execution, update the position data
nowPosition = GetPosition(e, tradeType);
}
dealAmount = _N((nowPosition ? nowPosition.Amount : 0) - (initPosition ? initPosition.Amount : 0), 6); // Calculate the number of transactions according to the initial position data and current position data
var doAmount = Math.min(tradeAmount - dealAmount, account.Stocks * MarginLevel, 4); // Calculate the remaining amount to be transacted according to the number of transactions and the available assets of the account
if (doAmount < MinStock) { // If the calculated transaction amount is less than the minimum transaction amount, stop the logic and skip out of the while loop
break;
}
prePrice = tradePrice; // Cache the transaction price in the current loop
e.SetDirection(tradeType == ORDER_TYPE_BUY ? "buy" : "sell"); // Set the direction of futures trading
orderId = tradeFunc(tradePrice, doAmount); // Place a transaction, the parameters are the calculated price, the number of orders placed for this time
} else { // If the orderId of the recorded order variable is not null, it indicates that an order has been placed
if (mode == 0 || Math.abs(tradePrice - prePrice) > maxSpace) { // If it is the maker mode, the current price and the last cached price exceed the maximum maker range
orderId = null; // Reset the orderId to a null value, and the order will be placed again in the next loop
}
var order = StripOrders(exchange, orderId); // Call StripOrders to find the order with ID of orderId in the list of pending orders
if (order == null) { // If it cannot be found, reset the orderId to a null value, too, and continue the next round of order placement
orderId = null;
}
}
Sleep(retryDelay); // A certain time is tentatively determined to control the frequency of the loop
}
if (dealAmount <= 0) { // At the end of the while loop, if the amount of dealAmount is less than or equal to 0, it means that the transaction failed to return the null value
return null;
}
return nowPosition; // If it's normal condition, returns to the latest position data
}
function coverFutures(e, orderType) { // Function for closing the position
var coverAmount = 0; // Declare a variable coverAmount with an initial assignment of 0 to record the amount of closed positions
while (true) {
var positions = _C(e.GetPosition); // Obtain the position
var ticker = GetTicker(e); // Obtain the current quotations
var found = 0; // Find the marker
for (var i = 0; i < positions.length; i++) { // Iterate through the array of positions
if (positions[i].Type == orderType) { // Find the position needed
if (coverAmount == 0) {
coverAmount = positions[i].Amount; // Record the position amount at the beginning, that is, the amount to be closed
}
if (positions[i].Type == ORDER_TYPE_BUY) { // Perform the closing position operation according to the position type
e.SetDirection("closebuy"); // Set the futures trading direction
e.Sell(ticker.Buy, positions[i].Amount); // Order function
} else {
e.SetDirection("closesell");
e.Buy(ticker.Sell, positions[i].Amount);
}
found++; // Marker accumulation
}
}
if (found == 0) { // If the marker variable found is 0, then there are no positions to process and the while loop is skipped
break;
}
Sleep(2000); // 2 seconds interval
StripOrders(e); // Cancel all the current pending orders
}
return coverAmount; // Return to the number of closed positions
}
function loop(pos) {
var tradeType = null; // Trading direction of initialization
if (typeof(pos) == 'undefined' || !pos) { // Determine if it is the first round of execution
tradeType = FirstTradeType;
pos = Trade(exchange, tradeType, OpAmount, OpMode, SlidePrice, MaxSpace, Interval); // First transaction
if (!pos) {
throw "Failure to open a position";
} else {
Log(tradeType == ORDER_TYPE_BUY ? "Open long positions to complete" : "Open short positions to complete", "average price:", pos.Price, "amount:", pos.Amount);
}
} else {
tradeType = pos.Type; // Continue to specify the direction of the transaction according to the direction of the position
}
var holdPrice = pos.Price; // Position price
var holdAmount = pos.Amount; // Position amount
var openFunc = tradeType == ORDER_TYPE_BUY ? exchange.Buy : exchange.Sell; // Long position, open position to buy, otherwise open position to sell
var coverFunc = tradeType == ORDER_TYPE_BUY ? exchange.Sell : exchange.Buy; // Long position, close position to sell, otherwise close position to buy
var reversePrice = 0; // Backhand price
var coverPrice = 0; // The price of closing the position
var canOpen = true; // Mark of opening position
if (tradeType == ORDER_TYPE_BUY) {
reversePrice = _N(holdPrice * (1 - StopLoss), 4); // Stop loss price
coverPrice = _N(holdPrice * (1 + StopProfit), 4); // Stop profit price
} else {
reversePrice = _N(holdPrice * (1 + StopLoss), 4);
coverPrice = _N(holdPrice * (1 - StopProfit), 4);
}
var coverId = null;
var msg = "Position price" + holdPrice + "stop loss price:" + reversePrice;
for (var i = 0; i < 10; i++) { // It controls up to 10 orders
if (coverId) { // The order ID is empty, and the break is not triggered. Continue the loop until 10 times
break;
}
if (tradeType == ORDER_TYPE_BUY) { // Place an order according to the direction and place a closing position order, i.e. an order to stop profit
exchange.SetDirection("closebuy");
coverId = exchange.Sell(coverPrice, holdAmount, msg);
} else {
exchange.SetDirection("closesell");
coverId = exchange.Buy(coverPrice, holdAmount, msg);
}
Sleep(Interval);
}
if (!coverId) { // Failed to place an order for 10 times and threw an error, the strategy stopped
StripOrders(exchange); // Cancel all the pending orders
Log("Failed to place an order", "@") // Add push alerts
throw "Failed to place an order"; // Throw an error to stop the robot
}
while (true) { // Enter the loop of detecting the backhand
Sleep(Interval);
var ticker = GetTicker(exchange); // Get the latest quotation
if ((tradeType == ORDER_TYPE_BUY && ticker.Last < reversePrice) || (tradeType == ORDER_TYPE_SELL && ticker.Last > reversePrice)) { // Detect trigger stop loss and backhand
StripOrders(exchange); // Cancel all the pending orders
var coverAmount = coverFutures(exchange, tradeType); // Closinng all the positions
if (_Failed >= MaxLoss) { // If the maximum stop loss times (backhand times) are exceeded, skip out of the loop and start again
Counter.f++; // Record a failure
Log("Exceed the maximum number of failures", MaxLoss);
break; // Skip out of the loop
}
var reverseAmount = _N(coverAmount * ReverseRate, 4); // Double the trading volume according to the amount of closed positions
var account = GetAccount(exchange, true); // Update the account information. At this time, no assets can be frozen
// Check whether the account assets are sufficient. If not, skip out of the loop and start again, as _ Failed >= MaxLoss
if (_N(account.Stocks * MarginLevel, 4) < reverseAmount) { // Check whether the assets are sufficient
Log("Open a backhand position if there is no currencies, it needs to be opened: ", reverseAmount, "amount, only", account.Stocks, "currencies");
Counter.f++;
break;
}
var reverseType = tradeType; // Record the reverse operation type. The default is forward position
if (ReverseMode == 0) { // The backhand mode affects the adjustment, that is, if the parameter is set to the reverse position, adjust here
reverseType = tradeType == ORDER_TYPE_BUY ? ORDER_TYPE_SELL : ORDER_TYPE_BUY; // Reverse the position means that if you have a long position just now, you shall go short at this time. If you have a short position just now, you shall go long at this time
}
var pos = Trade(exchange, reverseType, reverseAmount, OpMode, SlidePrice, MaxSpace, Interval); // Double the operation of placing an order
if (pos) { // Detect the positions after trading logic execution
Log(reverseType == ORDER_TYPE_BUY ? "long position" : "short position", "Complete it by doubling the opening position");
}
return pos; // Return to the position structure
} else { // Logic executed when no backhand is triggered
var orders = _C(exchange.GetOrders); // When the stop-profit order is filled, the number of wins recorded will be increased by 1
if (orders.length == 0) {
Counter.s++;
var account = GetAccount(exchange, true); // Update account assets
LogProfit(account.Stocks, account); // Print account assets
break;
}
}
}
// If it is not returned normally in the while loop, return to null. For example, if the profit stop is successful, the number of failures is exceeded, and the asset is insufficient
return null;
}
function onexit() { // When the robot stops, execute the round-off function onexit
StripOrders(exchange); // Cancel all the pending orders
Log("Exit");
}
function main() {
if (exchange.GetName().indexOf("Futures") == -1) { // Check whether the first exchange object currently added is a futures exchange
throw "Only futures are supported, but not spots for now";
}
// EnableLogLocal(SaveLocal);
if (exchange.GetRate() != 1) { // Do not enable exchange rate conversion
Log("Exchange rate conversion disabled");
exchange.SetRate(1);
}
StopProfit /= 100; // The parameter is processed as a decimal number. If StopProfit is 1, it means that stop profit when it is 1%. Recalculate the assignment. The value of StopProfit is 0.01, that is, 1%
StopLoss /= 100; // Stop loss (backhand), same as above
var eName = exchange.GetName();
if (eName == "Futures_CTP") { // Detect whether the first exchange object added is a commodity futures. If so, throw an error message to stop the robot
throw "Only digital currency futures are supported for now"
}
exchange.SetContractType(Symbol); // Set the digital currency contract code, i.e. the contract to be traded and operated
exchange.SetMarginLevel(MarginLevel); // Set leverage
Interval *= 1000; // The polling interval parameter is converted from seconds to milliseconds
SetErrorFilter("502:|503:|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF"); // Set the type of error to be blocked
StripOrders(exchange); // Cancel all the pending orders
OrgAccount = GetAccount(exchange, true); // Get the current account information
LogStatus("start successfully"); // Update status bar information
var pos = null; // Initialize the local variable pos to null in the main function, which is used to record the position data structure
var positions = GetPosition(exchange); // Get the current positions. Call the encapsulated GetPosition without the orderType parameter to get all positions. Note that the API interface exchange.GetPosition is not called
if (positions.length == 1) { // If there is a position at the beginning, assign a value to the pos variable
pos = positions[0];
Log("A position was found, and the progress has been restored automatically");
} else if (positions.length > 1) { // When there are multiple positions, the strategy cannot be operated and the strategy throws an error to stop the robot
throw "More than 1 position was found";
}
while (true) { // Strategy main loop
pos = loop(pos); // The main function loop of the trading logic is executed, and pos is used as a parameter, and the new position data structure is returned
if (!pos) { // This condition is triggered and null is returned. For example, if the profit is stopped successfully, the number of failures is exceeded, and the asset is insufficient
_Failed = 0; // Reset the time of stop loss to 0 and start again
} else {
_Failed++; // Accumulated time of stop loss
}
Sleep(Interval);
}
}
حکمت عملی کا کوڈ پڑھنے کے بعد، ہم دیکھ سکتے ہیں کہ حکمت عملی کا منطق پیچیدہ نہیں ہے اور بہت سے کوڈ نہیں ہیں، لیکن ڈیزائن شاندار ہے اور یہ بہت سے مقامات پر حوالہ کے طور پر استعمال کیا جا سکتا ہے.
حکمت عملی ٹریڈنگ منطق کا بنیادی کامloop
تقریب، جس کے مرکزی لوپ میں بار بار بلایا جاتا ہےmain
جبloop
فنکشن عملدرآمد شروع کرتا ہے ، یہ پہلے آرڈر پوزیشن رکھتا ہے ، پھر منافع کو روکنے کے لئے اوڈر رکھتا ہے اور اسٹاپ منافع کے آرڈر کو پورا کرنے کا انتظار کرتا ہے۔ اس کے بعد ، یہ پتہ لگانے کی حالت میں داخل ہوتا ہے اور دونوں اشیاء کا پتہ لگاتا ہے۔
حکمت عملی کی منطق کو آسانی سے بیان کیا گیا ہے ، لیکن پھر بھی کچھ دیگر تفصیلات ہیں ، جیسے زیادہ سے زیادہ بیک ہینڈ اوقات کی ترتیب ، دستیاب اکاؤنٹ کے اثاثوں کا پتہ لگانے ، اور 10 بار کی زیادہ سے زیادہ تعداد میں آرڈر کی ناکامیوں کی پروسیسنگ۔
حکمت عملی میں کچھ افعال مختلف پیرامیٹرز کے مطابق مختلف طریقے سے برتاؤ کرنے کے لئے ڈیزائن کیا گیا ہے، جیسے:StripOrders
فنکشنGetAccount
فنکشنGetPosition
فنکشن۔ ان افعال میں پاس کردہ پیرامیٹر کے فرق کے مطابق مختلف طرز عمل ہوتا ہے۔ اس طرح ، کوڈ کو اچھی طرح سے دوبارہ استعمال کیا جاتا ہے ، کوڈ کی بے کارگی سے گریز کیا جاتا ہے ، اور حکمت عملی کا ڈیزائن جامع اور سمجھنے میں آسان ہے۔
اصل حکمت عملی:https://www.fmz.com/strategy/3648
بیک ہینڈ ڈبلنگ کے کچھ خطرات ہیں، خاص طور پر فیوچر میں، حکمت عملی صرف سیکھنے کے مقصد کے لیے ہے، حقیقی بوٹ میں احتیاط، براہ مہربانی اپنے تبصرے چھوڑنے کے لئے آزاد محسوس کریں اور ہم ایک بحث کر سکتے ہیں.