টেলিভিশনের ঘণ্টা থেকে বার্তা পাঠানো হচ্ছেঃ ওপেনলং ওপেনশর্ট খোলা ক্লোজ লং CloseShort ফাঁকা
অ্যালার্মের নামটি আনুষ্ঠানিকভাবে পূরণ করুন, বার্তার বিষয়বস্তু উপরে ইংরেজি (শুধুমাত্র ইংরেজি লিখুন, স্পেস এবং অন্যান্য চিহ্ন ছাড়াই) সঠিক ওয়েবহুক URL পূরণ করতে ভুলবেন না
তথ্যসূত্রঃhttps://www.fmz.com/bbs-topic/5533
ব্যাখ্যাঃ
টিভি থেকে একটি স্টপ-হ্রাস সংকেত গ্রহণ করা হয়, কিন্তু টিভি সংকেতটি K- রড শেষ হওয়ার পরে প্রেরণ করা হয়, এই স্ক্রিপ্টের স্টপ-হ্রাসটি প্লাগগুলি প্রতিরোধ করার জন্য ডিজাইন করা হয়েছে; এটি টিভিগুলির তুলনায় কিছুটা বড় হতে পারে, প্রায় ০.২৫ গুণ বেশি (যেমন, ০.৭৫% এর মতো) ।
////TradingView信号 ////从TradingView接收开仓、平仓信号(OpenLong/CloseLong,OpenShort/CloseShort)执行开仓、平仓操作。 ////记得填写正确的Webhook URL 参考地址:https://www.fmz.com/bbs-topic/5533 ////暂时只测试了U本位交易。 ////只能做一个多单,如果当前有多单,不再继续开多;同样的逻辑适用于空单; 0.1.0 ////将夏天不打你的代码融入进来 V 0.1.3 2023年4月29日 03:35:31 策略地址:https://www.fmz.com/strategy/320782(源代码已经不再维护) ////夏天不打你的微信:wd1061331106 ////V0.1.9//根据原来的0.1.4进行了修改,重启后可以更新止盈止损价格;2024年11月22日 15:38:45 ////如果遇到交易平台发送的Too many requests的消息,不会停机(非常棒)。 ////V0.1.10 修正了挂单止盈成交之后,收到平仓信息报错的问题。2024年11月22日 21:20:00 // 参数设置 // 策略参数变量 // 基本设置 var _Currency = TradeCurrency; // 交易对 var _Interval = Interval; // 程序运行周期 var _UseQuarter = UseQuarter; // 季度合约,默认USDT永续合约 var _EnableMessageSend = EnableMessageSend; // 推送消息 // 下单设置 var _MarginLevel = MarginLevel; // 杠杆倍数 var _OrderSize = OrderSize; // 下单数量/张数 var _OrderByMargin = OrderByMargin; // 根据下单保证金来确定下单数量 var _OrderMarginPercent = OrderMarginPercent; // 下单保证金百分比%(根据初始资金计算) var _PricePrecision = PricePrecision; // 下单价格精度 var _AmountPrecision = AmountPrecision; // 下单数量精度 var _OneSizeInCurrentCoin = OneSizeInCurrentCoin; // U本位合约中,一张ETH所代表的ETH数量 var _QuarterOneSizeValue = QuarterOneSizeValue; // 币本位合约中,一张ETH所代表的USDT数量 // 止盈止损 var _UseStopLoss = UseStopLoss; // 使用止损 var _TakeProfitPercent = TakeProfitPercent; // 止盈价格百分比% var _TakeProfitAmount = TakeProfitAmount; // 止盈数量百分比% var _TakeProfitPrice = 0; // 止盈价格,用于显示 var _StopLossPercent = StopLossPercent; // 止损价格百分比 var _UseTrackingTakeProfit = UseTrackingTakeProfit; // 使用回调止盈 var _CallBakcPercent = CallBakcPercent; // 回调百分比% var takeProfitOrderId; //记录止盈单1 var ALLPrice_zhicheng = 0; //记录支撑价格 // 统计变量 var _InitAsset = 0; var _ProfitLocal = 0; var _TakeProfitCount = 0; var _TradeCount = 0; var StrategyRunTimeStampString = "strategy_run_time"; var _StrategyDatas = { start_run_timestamp: 0, others: "" }; var _UserDatas = null; // 相对固定参数 var _MaintenanceMarginRate = 0.004 // 维持保证金率 var _TakerFee = 0.0005; // 吃单手续费 var _IsUsdtStandard = false; // USDT本位开单和结算 var stopLossPrice = 0; //用于记录支撑价格,方便进行止损操作; // 全局变量 var position; var baseMargin; var assetPrecision;//获取资产精度,并将其存储在全局变量中: var pricePrecision; // 在全局变量中添加一个新变量,用于存储价格精度 var DEFAULT_ASSET_PRECISION = 3; var DEFAULT_PRICE_PRECISION = 2; // 在这里添加价格精度的默认值 var hasOpenedLong = false; // 跟踪是否已经开过多单 var hasOpenedShort = false; // 跟踪是否已经开过空单 var _HasTakeProfit = false; //是否止盈过? var _TriggeredTakeProfit = false; // 是否触发了回调止盈 var _PeakPriceInPosition = 0; // 持仓中价格的峰值点(最高/最低点) var lock = false; //锁定止损价格一段时间,保证开仓之后不会因为TV上的止损价格未发生变化而导致的立刻平仓。 var lastUpdateTime = 0; //记录上次止损价格更新时间的变量 // 保存程序起始运行时间 秒级时间戳 function saveStrategyRunTime() { var local_data_strategy_run_time = _G(StrategyRunTimeStampString); if (local_data_strategy_run_time == null) { _StrategyDatas.start_run_timestamp = Unix(); _G(StrategyRunTimeStampString, _StrategyDatas.start_run_timestamp); } else { _StrategyDatas.start_run_timestamp = local_data_strategy_run_time; } } // 设置程序起始运行时间 秒级时间戳 function setStrategyRunTime(timestamp) { _G(StrategyRunTimeStampString, timestamp); _StrategyDatas.start_run_timestamp = timestamp; } // 计算两个时间戳之间的天数,参数是秒级时间戳 function getDaysFromTimeStamp(start_time, end_time) { if (end_time < start_time) return 0; return Math.trunc((end_time - start_time) / (60 * 60 * 24)); } // 保存数据到本地 function saveUserDatasLocal() { _UserDatas = { init_assets: _InitAsset, profit_local: _ProfitLocal, take_profit_count: _TakeProfitCount, trade_count: _TradeCount }; // 存储到本地 _G(exchange.GetLabel(), _UserDatas); Log("已把所有数据保存到本地."); } // 读取用户本地数据,程序启动时候运行一次 function readUserDataLocal() { var user_data = _G(exchange.GetLabel()); if (user_data == null) { _InitAsset = getAccountAsset(_C(exchange.GetPosition), _C(exchange.GetAccount), _C(exchange.GetTicker)); _UserDatas = { init_assets: _InitAsset, profit_local: 0, take_profit_count: 0, trade_count: 0 }; } else { _UserDatas = user_data; } } // 清除用户本地数据,交互按钮点击运行 function clearUserDataLocal() { _G(exchange.GetLabel(), null); Log(exchange.GetLabel(), ":已清除本地数据."); } //将购买数量调整为合适的精度: function fixAmountPrecision(amount, _AmountPrecision) { return parseFloat(amount.toFixed(_AmountPrecision)); } // 添加一个新函数,用于将价格调整到合适的精度 function fixPricePrecision(price, _PricePrecision) { return parseFloat(price.toFixed(_PricePrecision)); } // 策略交互 function runCmd(cmd) { if (cmd) { // 检测交互命令 Log("接收到的命令:", cmd, "#FF1CAE"); if (cmd.indexOf("ClearLocalData:") == 0) { // 清除本地数据 clearUserDataLocal(); } else if (cmd.indexOf("SaveLocalData:") == 0) { // 保存数据到本地 saveUserDatasLocal(); } else if (cmd.indexOf("ClearLog:") == 0) { // 清除日志 var log_reserve = cmd.replace("ClearLog:", ""); LogReset(Number(log_reserve)); } else if (cmd.indexOf("OrderSize:") == 0) { // 修改下单张数 if (_OrderByMargin) { Log("已经使用保证金数量来下单,无法直接修改下单数量!"); } else { var order_size = Number(cmd.replace("OrderSize:", "")); _OrderSize = order_size; Log("下单张数已经修改为:", _OrderSize); } } else if (cmd.indexOf("OrderMarginPercent:") == 0) { // 修改下单保证金百分比 if (_OrderByMargin) { var order_margin_percent = Number(cmd.replace("OrderMarginPercent:", "")); _OrderMarginPercent = order_margin_percent; Log("下单保证金百分比:", _OrderMarginPercent, "%"); } else { Log("没有打开根据保证金数量下单,无法修改下单保证金百分比!"); } } } } //// 检查重启后是否存在多单或空单 function initialize() { // 检查重启后是否存在多单或空单 var positions = exchange.GetPosition(); for (var i = 0; i < positions.length; i++) { if (positions[i].Type === PD_LONG || positions[i].Type === PD_LONG_YD) { hasOpenedLong = true; stopLossPrice = positions[i].Price * (1 - _StopLossPercent / 100);//更新止损价格--多单 Log("存在多单,止损价格更新:",stopLossPrice); } else if (positions[i].Type === PD_SHORT || positions[i].Type === PD_SHORT_YD) { hasOpenedShort = true; stopLossPrice = positions[i].Price * (1 + _StopLossPercent / 100);//更新止损价格--空单//更新止损价格--空单 Log("存在空单,止损价格更新:",stopLossPrice); } } } // 交易函数 function orderDirectly(distance, price, amount) { var tradeFunc = null; if (amount <= 0) { throw "设置的参数有误,下单数量已经小于0!" } if (distance == "buy") { tradeFunc = exchange.Buy; } else if (distance == "sell") { tradeFunc = exchange.Sell; } else if (distance == "closebuy") { tradeFunc = exchange.Sell; Log("空单平仓:",price,"数量:",amount); } else { tradeFunc = exchange.Buy; Log("多单平仓:",price,"数量:",amount); } exchange.SetDirection(distance); return tradeFunc(price, amount); } function openLong(price, amount) { var real_amount = getRealOrderSize(price, amount); return orderDirectly("buy", price, real_amount); } function openShort(price, amount) { var real_amount = getRealOrderSize(price, amount); return orderDirectly("sell", price, real_amount); } function coverLong(price, amount) {//多单平仓 if (takeProfitOrderId) {// 取消止盈单 exchange.CancelOrder(takeProfitOrderId); Log("取消多单止盈单"); takeProfitOrderId = null; _TakeProfitPrice = 0; //更新止盈价格 } Sleep(200); return orderDirectly("closebuy", price, amount); } function coverShort(price, amount) {//平仓空单 if (takeProfitOrderId) {// 取消止盈单 exchange.CancelOrder(takeProfitOrderId); Log("取消空单止盈单"); takeProfitOrderId = null; _TakeProfitPrice = 0; //更新止盈价格 } Sleep(200); return orderDirectly("closesell", price, amount); } // 重新计算下单数量 function getRealOrderSize(price, amount) { var real_price = price == -1 ? _C(exchange.GetTicker).Last : price; if (_OrderByMargin) { if (_IsUsdtStandard) { _OrderSize = _N(_InitAsset * (_OrderMarginPercent / 100) / real_price * _MarginLevel / _OneSizeInCurrentCoin, _AmountPrecision); } else { _OrderSize = _N(_InitAsset * (_OrderMarginPercent / 100) * _MarginLevel * real_price / _QuarterOneSizeValue, _AmountPrecision); } } else { _OrderSize = amount; } return _OrderSize; } // 获取单向持仓的收益和收益% function getSinglePositionProfit(position, ticker) { if (position.length == 0) return [0, 0]; var price = ticker.Last; var position_margin = getSinglePositionMargin(position, ticker); var position_profit_percent = position[0].Type == PD_LONG ? ((price - position[0].Price) / position[0].Price) * _MarginLevel : ((position[0].Price - price) / position[0].Price) * _MarginLevel; var position_profit = position_margin * position_profit_percent; return [position_profit, position_profit_percent]; } // 计算强平价格 function calculateForcedPrice(account, position, ticker) { var position_profit = 0; var total_avail_balance = 0; var forced_price = 0; var position_margin = getSinglePositionMargin(position, ticker); [position_profit, position_profit_percent] = getSinglePositionProfit(position, ticker); if (_IsUsdtStandard) { total_avail_balance = position_profit > 0 ? account.Balance + position_margin + account.FrozenBalance - position_profit : account.Balance + position_margin + account.FrozenBalance; if (position[0].Type == PD_LONG) { forced_price = (((_MaintenanceMarginRate + _TakerFee) * _MarginLevel * account.FrozenBalance - total_avail_balance) / _OneSizeInCurrentCoin + (position[0].Amount * position[0].Price)) / (position[0].Amount - (_MaintenanceMarginRate + _TakerFee) * position[0].Amount); } else { forced_price = (((_MaintenanceMarginRate + _TakerFee) * _MarginLevel * account.FrozenBalance - total_avail_balance) / _OneSizeInCurrentCoin - (position[0].Amount * position[0].Price)) / (-1 * position[0].Amount - (_MaintenanceMarginRate + _TakerFee) * position[0].Amount); } } else { total_avail_balance = position_profit > 0 ? account.Stocks + position_margin + account.FrozenStocks - position_profit : account.Stocks + position_margin + account.FrozenStocks; if (position[0].Type == PD_LONG) { forced_price = (_MaintenanceMarginRate * position[0].Amount + position[0].Amount) / (total_avail_balance / _QuarterOneSizeValue + position[0].Amount / position[0].Price); } else { forced_price = (_MaintenanceMarginRate * position[0].Amount - position[0].Amount) / (total_avail_balance / _QuarterOneSizeValue - position[0].Amount / position[0].Price); } } if (forced_price < 0) forced_price = 0; return forced_price; } // 计算最大可下单张数 function getMaxOrderSize(margin_level, ticker, account) { var max_order_size = 0; if (_IsUsdtStandard) { max_order_size = account.Balance * margin_level / (_OneSizeInCurrentCoin * ticker.Last); } else { max_order_size = account.Stocks * ticker.Last / _QuarterOneSizeValue * margin_level; } return _N(max_order_size, _AmountPrecision); } // 获取单个持仓占用保证金 function getSinglePositionMargin(position, ticker) { var position_margin = 0; if (position.length > 0) { if (_IsUsdtStandard) { position_margin = position[0].Amount * _OneSizeInCurrentCoin * ticker.Last / _MarginLevel; } else { position_margin = position[0].Amount * _QuarterOneSizeValue / ticker.Last / _MarginLevel; } } return position_margin; } // 获取账户资产 function getAccountAsset(position, account, ticker) { // 计算不同情况下的账户初始资产 var account_asset = 0; var position_margin = getSinglePositionMargin(position, ticker); if (_IsUsdtStandard) { if (position.length > 0) { account_asset = account.Balance + account.FrozenBalance + position_margin; } else { account_asset = account.Balance + account.FrozenBalance; } } else { if (position.length > 0) { account_asset = account.Stocks + account.FrozenStocks + position_margin; } else { account_asset = account.Stocks + account.FrozenStocks; } } return account_asset; } // 收益统计 function calculateProfit(ticker) { // 重新获取一下账户持仓与资产 var position = _C(exchange.GetPosition); var account = _C(exchange.GetAccount); // 当前总收益 - 上一次总收益 = 本次的收益 var current_profit = (getAccountAsset(position, account, ticker) - _InitAsset) - _ProfitLocal; _ProfitLocal += current_profit; if (current_profit > 0) { _TakeProfitCount++; } _TradeCount++; LogProfit(_N(_ProfitLocal, 4), " 本次收益:", _N(current_profit, 6)); Log(getAccountAsset(position, account, ticker), 4), " 当前资金:", _N(getAccountAsset(position, account, ticker), 6); saveUserDatasLocal(); } // 是否还够资金下单 function isEnoughAssetToOrder(order_size, ticker) { var is_enough = true; var account = _C(exchange.GetAccount); if (_IsUsdtStandard) { if (account.Balance < order_size * ticker.Last * _OneSizeInCurrentCoin / _MarginLevel) { is_enough = false; } } else { if (account.Stocks < order_size * _QuarterOneSizeValue / ticker.Last / _MarginLevel) { is_enough = false; } } return is_enough; } // 止损--------------------- function stopLoss(stopLossPrice, position, ticker) { var stop_loss_price = 0; var price = ticker.Last; if (position.length == 1 && _UseStopLoss) { if (position[0].Type == PD_LONG) { stop_loss_price = stopLossPrice; //设定止损价格 if (price < stop_loss_price) { coverLong(-1, position[0].Amount); _HasTakeProfit = false; calculateProfit(ticker); //统计收益 _TrendWhenTakeProfitOrStopLoss = 1; _HadStopLoss = true; Log("多单止损。止损价格:", _N(stop_loss_price, 6), ", 持仓价格:", _N(position[0].Price), _EnableMessageSend ? "@" : "#FF1CAE"); } } else if (position[0].Type == PD_SHORT) { stop_loss_price = stopLossPrice; //设定止损价格 if (price > stop_loss_price) { coverShort(-1, position[0].Amount); _HasTakeProfit = false; calculateProfit(ticker); //统计收益 _TrendWhenTakeProfitOrStopLoss = -1; _HadStopLoss = true; Log("空单止损。止损价格:", _N(stop_loss_price, 6), ", 持仓价格:", _N(position[0].Price), _EnableMessageSend ? "@" : "#FF1CAE"); } } } } // 止盈 function takeProfit(position, ticker) { var take_profit_price = 0; var price = ticker.Last; if (position.length == 1) { if (position[0].Type == PD_LONG) { take_profit_price = position[0].Price * (1 + _TakeProfitPercent / 100); //设定止盈价格 _TakeProfitPrice = take_profit_price; //记录止盈价格 if (price > take_profit_price) { var takeProfitAmount = fixAmountPrecision(position[0].Amount * _TakeProfitAmount / 100, _AmountPrecision); // 调整数量精度 //coverLong(-1, takeProfitAmount); _HasTakeProfit = true; calculateProfit(ticker); //统计收益 _TrendWhenTakeProfitOrStopLoss = 1; _HadTakeProfit = true; Log("多单止盈。止盈价格:", _N(take_profit_price, 6), ", 持仓价格:", _N(position[0].Price), _EnableMessageSend ? "@" : "#FF1CAE"); _TriggeredTakeProfit = true; //打开回调止盈开关 _PeakPriceInPosition = price; // 记录价格高点 takeProfitOrderId = null; } } else if (position[0].Type == PD_SHORT) { take_profit_price = position[0].Price * (1 - _TakeProfitPercent / 100); _TakeProfitPrice = take_profit_price; //记录止盈价格 if (price < take_profit_price) { var takeProfitAmount = fixAmountPrecision(position[0].Amount * _TakeProfitAmount / 100, _AmountPrecision); // 调整数量精度 //coverShort(-1, takeProfitAmount); _HasTakeProfit = true; calculateProfit(ticker); //统计收益 _TrendWhenTakeProfitOrStopLoss = -1; _HadTakeProfit = true; Log("空单止盈。止盈价格:", _N(take_profit_price, 6), ", 持仓价格:", _N(position[0].Price), _EnableMessageSend ? "@" : "#FF1CAE"); _TriggeredTakeProfit = true; //回调止盈开关打开 _PeakPriceInPosition = price; // 记录价格高点 takeProfitOrderId = null; } } } } // 回调止盈 function trackingTakeProfit(position, ticker) { var take_profit_price = 0; var trigger_price = 0; var price = ticker.Last; if (position.length > 0 && _UseTrackingTakeProfit) { if (position[0].Type == PD_LONG) { // 多单持仓 if (price > position[0].Price * (1 - _CallBakcPercent / 100)) {_TriggeredTakeProfit = true;} if (_TriggeredTakeProfit) {// 止盈回调代码(开关开启,监控是否止盈) _PeakPriceInPosition = price > _PeakPriceInPosition ? price : _PeakPriceInPosition; // 更新价格高点 take_profit_price = _PeakPriceInPosition * (1 - _CallBakcPercent / 100); // 计算回调的止盈价格 if (price < take_profit_price) {//如果价格低于回调止盈价格,则止盈 coverLong(-1, position[0].Amount); // 平多 _HasTakeProfit = false; calculateProfit(ticker); //统计收益 _TriggeredTakeProfit = false; // 复位触发标记 _HadTakeProfit = true; // 记录发生了止盈 Log("多单回调止盈:持仓中价格高点:", _N(_PeakPriceInPosition, 6), ", 止盈价格:", _N(take_profit_price, 6), ", 当前价格:", _N(price, 6), ", 持仓价格:", _N(position[0].Price, 6), _EnableMessageSend ? "@" : "#FF1CAE"); } } } else if (position[0].Type == PD_SHORT) { // 空单持仓 if (price < position[0].Price * (1 + _CallBakcPercent / 100)) {_TriggeredTakeProfit = true;} if (_TriggeredTakeProfit) { // 已达到触发价格,监控是否止盈 _PeakPriceInPosition = price < _PeakPriceInPosition ? price : _PeakPriceInPosition; // 更新价格低点 take_profit_price = _PeakPriceInPosition * (1 + _CallBakcPercent / 100); // 计算回调的止盈价格 if (price > take_profit_price) { coverShort(-1, position[0].Amount); // 平空 _HasTakeProfit = false; calculateProfit(ticker); //统计收益 _TriggeredTakeProfit = false; // 复位触发标记 _HadTakeProfit = true; // 记录发生了止盈 Log("空单回调止盈:持仓中价格低点:", _N(_PeakPriceInPosition, 6), ", 止盈价格:", _N(take_profit_price, 6), ", 当前价格:", _N(price, 6), ", 持仓价格:", _N(position[0].Price, 6), _EnableMessageSend ? "@" : "#FF1CAE"); } } } } } // 下单 function order(long, short, position, ticker) { var position_size = position.length > 0 ? position[0].Amount : 0; var position_type = position.length > 0 ? position[0].Type : null; if (long) { //判断是否持仓 if (position_size > 0 && position_type == PD_SHORT) { //如果当前持有空仓 coverShort(-1, position_size); //平掉空仓 calculateProfit(ticker); //统计收益 } else if (position_size > 0 && position_type == PD_LONG) { //如果当前持有多仓 Log("持有多单,不继续开多"); // 多单持仓,不重复下单 return; } else { } ////开多单 if (isEnoughAssetToOrder(_OrderSize, ticker)) { // 是否还够资金下单 openLong(-1, _OrderSize); //开多单 _HadStopLoss = false; //重置 _HadTakeProfit = false; //重置 lastUpdateTime = new Date().getTime(); //开单平单之后,更新时间 Sleep(500); // 挂多单止盈单 try { var takeProfitPrice = ticker.Buy * (1 + _TakeProfitPercent / 100); //设定止盈价格 takeProfitPrice = fixPricePrecision(takeProfitPrice, _PricePrecision); //调整价格精度 var takeProfitAmount = _OrderSize * _TakeProfitAmount / 100; //设定止盈数量 takeProfitAmount = fixAmountPrecision(takeProfitAmount, _AmountPrecision); //调整数量精度 _TakeProfitPrice = takeProfitPrice; //更新止盈价格--多单 stopLossPrice = ticker.Buy * (1 - _StopLossPercent / 100);//更新止损价格--多单 Log("开仓价格:",ticker.Buy,"止损价格:", stopLossPrice); //输出开仓价格,止损价格 exchange.SetDirection("closebuy"); // 设置止盈平多交易方向 takeProfitOrderId = exchange.Sell(takeProfitPrice, takeProfitAmount); //挂止盈单 Log("挂多单止盈单,价格:", takeProfitPrice, ",数量:", takeProfitAmount); //输出日志 } catch (error) { Log("挂多单止盈单失败:", error.message, "错误详情:", error); takeProfitOrderId = null; } } else { throw "保证金不足!"; } } else if (short) { ////判断是否持仓 if (position_size > 0 && position_type == PD_LONG) { //如果当前持有多仓 coverLong(-1, position_size); //平掉多仓 calculateProfit(ticker); //统计收益 } else if (position_size > 0 && position_type == PD_SHORT) { Log("持有空单,不继续开空"); // 多单持仓,不重复下单// 空单持仓,不重复下单 return; } else { } ////开空单 if (isEnoughAssetToOrder(_OrderSize, ticker)) { openShort(-1, _OrderSize); //开空单 _HadStopLoss = false; //重置 _HadTakeProfit = false; //重置 lastUpdateTime = new Date().getTime(); //开单平单之后,更新时间 Sleep(500); // 挂空单止盈单 try { var takeProfitPrice = ticker.Sell * (1 - _TakeProfitPercent / 100); //设定止盈数量 takeProfitPrice = fixPricePrecision( takeProfitPrice , _PricePrecision); //调整价格精度 var takeProfitAmount = _OrderSize * _TakeProfitAmount/100; //设定止盈数量 takeProfitAmount = fixAmountPrecision(takeProfitAmount, _AmountPrecision ); //调整数量精度 _TakeProfitPrice = takeProfitPrice; //更新止盈价格--空单 stopLossPrice = ticker.Sell * (1 + _StopLossPercent / 100); //更新止损价格--空单 Log("开仓价格:",ticker.Sell,"止损价格:", stopLossPrice); //输出开仓价格,止损价格 exchange.SetDirection("closesell"); //设置止盈平多交易方向 takeProfitOrderId = exchange.Buy(takeProfitPrice, takeProfitAmount); //挂止盈单 Log("挂空单止盈单,价格:", takeProfitPrice, ",数量:", takeProfitAmount); //输出日志 } catch (error) { Log("挂空单止盈单失败:", error.message, "错误详情:", error); takeProfitOrderId = null; } } else { throw "保证金不足!"; } } } // 状态栏信息打印 function printLogStatus(ticker, account, position) { var table_overview = { type: 'table', title: '策略总览', cols: ['开始时间', '已运行天数', '交易次数', '胜率', '预估月化%', '预估年化%', '界面显示代码来自大神“夏天不打你”'], rows: [] }; var table_account = { type: 'table', title: '账户资金', cols: ['当前资产', '初始资产', '可用余额', '冻结余额', '可下单张数', '收益', '收益%'], rows: [] }; var table_position = { type: 'table', title: '持仓情况', cols: ['交易币种', '杠杆倍数', '持仓均价', '方向', '数量', '保证金', '止损价格', '止盈价格', '浮动盈亏', '浮动盈亏%'], rows: [] }; var i = 0; // 策略总览 var the_running_days = getDaysFromTimeStamp(_StrategyDatas.start_run_timestamp, Unix()); var monthly_rate_of_profit = 0; if (the_running_days > 1) monthly_rate_of_profit = _ProfitLocal / _InitAsset / the_running_days * 30; table_overview.rows.push([ _D(_StrategyDatas.start_run_timestamp * 1000), //开始时间 the_running_days, //已运行天数 _TradeCount, //交易次数 _TradeCount == 0 ? 0 : (_N(_TakeProfitCount / _TradeCount * 100, 2) + "%"), //胜率 _N(monthly_rate_of_profit * 100, 2) + "%", //预估月化% _N(monthly_rate_of_profit * 12 * 100, 2) + "%", //预估年化% '地址:https://www.fmz.com/strategy/320782,作者微信:wd1061331106' //策略代谢请联系微信 ]); // 账户资金 var current_asset = getAccountAsset(position, account, ticker); var max_order_size = getMaxOrderSize(_MarginLevel, ticker, account); var asset_profit = current_asset - _InitAsset; var asset_profit_percent = asset_profit / _InitAsset; table_account.rows.push([ _N(current_asset, 4), //当前资产 _N(_InitAsset, 4), //初始资产 _N(_IsUsdtStandard ? account.Balance : account.Stocks, 4), //可用余额 _N(_IsUsdtStandard ? account.FrozenBalance : account.FrozenStocks, 4), //冻结余额 max_order_size, //可下单张数 _N(asset_profit, 4), //收益 _N(asset_profit_percent * 100, 2) + "%" //收益百分比 ]); // 持仓情况 var position_direction = ""; var forced_cover_up_price = 0; var position_profit_percent = 0; var position_profit = 0; var position_margin = 0; if (position.length == 0) { table_position.rows.push(["无持仓", "-", "-", "-", "-", "-", "-", "-", "-"]); } else { position_direction = position[0].Type == PD_LONG ? "多单" : "空单"; [position_profit, position_profit_percent] = getSinglePositionProfit(position, ticker); position_margin = getSinglePositionMargin(position, ticker); //forced_cover_up_price = calculateForcedPrice(account, position, ticker); table_position.rows.push([ exchange.GetCurrency(), //交易币种 _MarginLevel, //杠杆倍数 _N(position[0].Price, 4), //持仓均价 position_direction, //方向 position[0].Amount, //数量 _N(position_margin, 4), //保证金 _N(stopLossPrice, 4), //止损价格 _N(_TakeProfitPrice, 4), //止盈价格 _N(position_profit, 4), //浮动盈亏 _N((position_profit_percent * 100), 2) + "%" //浮动盈亏百分比 ]); } // 打印表格 LogStatus('`' + JSON.stringify(table_overview) + '`\n' + '`' + JSON.stringify(table_account) + '`\n' + '`' + JSON.stringify(table_position) + '`\n'); } // 初始化数据 function initDatas() { saveStrategyRunTime(); readUserDataLocal(); _InitAsset = _UserDatas.init_assets; _ProfitLocal = _UserDatas.profit_local; _TakeProfitCount = _UserDatas.take_profit_count; _TradeCount = _UserDatas.trade_count; if (_OrderByMargin) { getRealOrderSize(-1, _OrderSize); Log("已经重新计算下单张数:", _OrderSize); } } // 设置合约 function setContract() { _IsUsdtStandard = _Currency.includes("USDT") ? true : false; if (!IsVirtual()) { // 实盘设置 exchange.SetCurrency(_Currency); if (_UseQuarter) { exchange.SetContractType("quarter"); } else { exchange.SetContractType("swap"); } } else { // 回测设置 if (_IsUsdtStandard) { exchange.SetContractType("swap"); } else { exchange.SetContractType("quarter"); } } exchange.SetMarginLevel(_MarginLevel); exchange.SetPrecision(_PricePrecision, _AmountPrecision); } function main() { setContract(); // 设置合约 initDatas(); // 初始化数据 initialize();//检查是否存在多单和空单 while (true) { var command = GetCommand(); //获取WebHook消息 if (command) { // 检查 command 是否为空 Log("接收到的命令:", command, "#FF1CAE"); TV_FMZ_Strategy(command); //开单平单操作 } Take_Profit_Stop_Loss(); //止盈止损操作 Sleep(_Interval); // 程序运行间隔 } } //止盈止损函数 function Take_Profit_Stop_Loss(){ var ticker = _C(exchange.GetTicker); //获取当前交易对的市场行情信息 var account = _C(exchange.GetAccount); //获取交易账户信息的函数。 var position = _C(exchange.GetPosition); //获取当前交易所账户的持仓信息,并返回一个包含持仓信息的对象。 printLogStatus(ticker, account, position); // 状态栏信息打印 if (stopLossPrice > 0) { //止损处理 stopLoss(stopLossPrice, position, ticker); // 止损 } if(!_HasTakeProfit){ takeProfit(position, ticker); // 止盈 } if (_TriggeredTakeProfit) { trackingTakeProfit(position, ticker); // 回调止盈 } } // 执行对应的操作 function TV_FMZ_Strategy(action) { var ticker = _C(exchange.GetTicker); //获取当前交易对的市场行情信息 var account = _C(exchange.GetAccount); //获取交易账户信息的函数。 var position = _C(exchange.GetPosition); //获取当前交易所账户的持仓信息,并返回一个包含持仓信息的对象。 if (position.length > 1) { ////如果同时持有多空仓位则退出 Log(position); throw "同时有多空持仓!"; } switch (action) { // 处理消息对应的操作 case "OpenLong": order(1, 0, position, ticker); // 开多单 break; case "OpenShort": order(0, 1, position, ticker); // 开空单 break; case "CloseLong": if (position.length > 0) { if (position[0].Type === PD_LONG) { coverLong(-1, position[0].Amount); // 平多 _HasTakeProfit = false; _TriggeredTakeProfit = false; // 复位回调止盈开关 calculateProfit(ticker); //统计收益 } else { Log("当前持有空头持仓,无法平多"); } } else { Log("没有持仓,无法平多"); } break; case "CloseShort": if (position.length > 0) { if (position[0].Type === PD_SHORT) { coverShort(-1, position[0].Amount); // 平空 _HasTakeProfit = false; _TriggeredTakeProfit = false; // 复位回调止盈开关 calculateProfit(ticker); //统计收益 } else { Log("当前持有多头持仓,无法平空"); } } else { Log("没有持仓,无法平空"); } break; default: break; } }
মটরশুটিডিস্ক ডেমো ঠিকানাঃ https://www.fmz.com/robot/591982