/* 趋势策略V1.0 Version: 1.0 Author: summer Date: 2021.9.27 */ // 策略参数变量 // 基本设置 var _Currency = TradeCurrency; // 交易对 var _Interval = Interval; // 程序运行周期 var _UseQuarter = UseQuarter; // 季度合约,默认USDT永续合约 var _OnlyTrendJudgment = OnlyTrendJudgment; // 只做趋势判断,不交易 var _EnableMessageSend = EnableMessageSend; // 推送消息 // 趋势判断 var _RunInKLinePeriod = RunInKLinePeriod; // 按照K线周期执行策略核心 var _KLinePeriod = KLinePeriod; // K线周期(min) var _EmaLength = EmaLength; // EMA长度 var _EmaCoefficient = EmaCoefficient; // EMA有效系数 var _UseStddev = UseStddev; // 使用标准差 var _UseRecordsMiddleValue = UseRecordsMiddleValue; // 使用K线中值来计算标准差,否则使用K线收盘价 var _StddevLength = StddevLength; // 标准差长度 var _StddevDeviations = StddevDeviations; // 标准差偏差 // 下单设置 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 _StopLossPercent = StopLossPercent; // 止损百分比% var _UseTakeProfit = UseTakeProfit; // 使用止盈 var _TakeProfitPercent = TakeProfitPercent; // 止盈百分比% var _UseTrackingTakeProfit = UseTrackingTakeProfit; // 使用回调止盈 var _UsePositionRetracement = UsePositionRetracement; // 使用持仓回撤百分比止盈,否则使用价格回撤百分比止盈 var _TakeProfitTriggerPercent = TakeProfitTriggerPercent; // 回调止盈价格触发百分比% var _CallBakcPercent = CallBakcPercent; // 回调百分比% // 策略变量 var _LastBarTime = 0; // 最新的K线时间 var _TrendWhenTakeProfitOrStopLoss = 0; // 止盈止损时趋势的状态 1表示多 -1表示空 var _HadStopLoss = false; // 发生止损 var _TriggeredTakeProfit = false; // 是否触发了回调止盈 var _PeakPriceInPosition = 0; // 持仓中价格的峰值点(最高/最低点) var _HadTakeProfit = false; // 发生止盈 var _PriceCrossEMAStatus = 0; // 用来判断价格是否穿越均线。0:初始状态,没穿过(策略重启后的状态) -1:初始状态在均线下方 1:初始状态在均线上方 2:已经完成穿过 // 统计变量 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本位开单和结算 // 保存程序起始运行时间 秒级时间戳 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 runCmd() { var cmd = GetCommand(); 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 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; } else { tradeFunc = exchange.Buy; } 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) { return orderDirectly("closebuy", price, amount); } function coverShort(price, amount) { 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)); 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; } // 按照K线周期运行策略核心 function runInKLinePeriod(records) { var bar_time = records[records.length - 1].Time; if (_RunInKLinePeriod && _LastBarTime == bar_time) { return false; } _LastBarTime = bar_time; return true; } // 检查价格是否穿过均线 function checkPriceCrossEma(price, ema_value) { if (_PriceCrossEMAStatus == 0) { if (price <= ema_value) { _PriceCrossEMAStatus = -1; } else { _PriceCrossEMAStatus = 1; } } else if ((_PriceCrossEMAStatus == -1 && price >= ema_value) || (_PriceCrossEMAStatus == 1 && price <= ema_value)) { _PriceCrossEMAStatus = 2; // 完成穿过 } } // EMA的多空判断 function emaJudgment(records) { var ema_long = false; var ema_short = false; var price = records[records.length - 2].Close; // 已经收盘的K线的收盘价格 var ema = TA.EMA(records, _EmaLength); var ema_value = ema[ema.length - 2]; // 收盘K线对应ema值 var ema_upper = ema_value * (1 + _EmaCoefficient); var ema_lower = ema_value * (1 - _EmaCoefficient); checkPriceCrossEma(price, ema_value); if (price > ema_upper) { ema_long = true; } else if (price < ema_lower) { ema_short = true; } return [ema_long, ema_short]; } // 标准差判断 function stddevJudgment(records) { var in_trend = false; if (_UseStddev) { var records_data = []; for (var i = 0; i < records.length; i++) { records_data.push(_UseRecordsMiddleValue ? ((records[i].High + records[i].Low) / 2) : records[i].Close); } var stddev = talib.STDDEV(records_data, _StddevLength, _StddevDeviations); if (stddev[stddev.length - 1] > stddev[stddev.length - 2]) { in_trend = true; } } else { in_trend = true; } return in_trend; } // 趋势判断 function trendJudgment(records) { var long = false; var short = false; [long, short] = emaJudgment(records); var in_trend = stddevJudgment(records); long = (in_trend && long) ? true : false; short = (in_trend && short) ? true : false; if (long) { Log("当前趋势为:多", _EnableMessageSend ? "@" : "#00FF7F"); } else if (short) { Log("当前趋势为:空", _EnableMessageSend ? "@" : "#FF0000"); } else { Log("当前趋势为:震荡", _EnableMessageSend ? "@" : "#007FFF"); } return [long, short]; } // 止损 function stopLoss(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 = position[0].Price * (1 - _StopLossPercent / 100); if (price < stop_loss_price) { coverLong(-1, position[0].Amount); 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 = position[0].Price * (1 + _StopLossPercent / 100); if (price > stop_loss_price) { coverShort(-1, position[0].Amount); 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 && _UseTakeProfit) { if (position[0].Type == PD_LONG) { take_profit_price = position[0].Price * (1 + _TakeProfitPercent / 100); if (price > take_profit_price) { coverLong(-1, position[0].Amount); calculateProfit(ticker); _TrendWhenTakeProfitOrStopLoss = 1; _HadTakeProfit = true; Log("多单止盈。止盈价格:", _N(take_profit_price, 6), ", 持仓价格:", _N(position[0].Price), _EnableMessageSend ? "@" : "#FF1CAE"); } } else if (position[0].Type == PD_SHORT) { take_profit_price = position[0].Price * (1 - _TakeProfitPercent / 100); if (price < take_profit_price) { coverShort(-1, position[0].Amount); calculateProfit(ticker); _TrendWhenTakeProfitOrStopLoss = -1; _HadTakeProfit = true; Log("空单止盈。止盈价格:", _N(take_profit_price, 6), ", 持仓价格:", _N(position[0].Price), _EnableMessageSend ? "@" : "#FF1CAE"); } } } } // 回调止盈 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 (_TriggeredTakeProfit) { // 已达到触发价格,监控是否止盈 _PeakPriceInPosition = price > _PeakPriceInPosition ? price : _PeakPriceInPosition; // 更新价格高点 if (_UsePositionRetracement) { take_profit_price = _PeakPriceInPosition - (_PeakPriceInPosition - position[0].Price) * (_CallBakcPercent / 100); // 计算回调的止盈价格 } else { take_profit_price = _PeakPriceInPosition * (1 - _CallBakcPercent / 100); // 计算回调的止盈价格 } if (price < take_profit_price) { coverLong(-1, position[0].Amount); // 平多 calculateProfit(ticker); _TriggeredTakeProfit = false; // 复位触发标记 _TrendWhenTakeProfitOrStopLoss = 1; // 记录止盈时候的趋势 _HadTakeProfit = true; // 记录发生了止盈 Log("多单回调止盈:持仓中价格高点:", _N(_PeakPriceInPosition, 6), ", 止盈价格:", _N(take_profit_price, 6), ", 当前价格:", _N(price, 6), ", 持仓价格:", _N(position[0].Price, 6), _EnableMessageSend ? "@" : "#FF1CAE"); } } else { // 监控是否达到回调止盈的触发价格 trigger_price = position[0].Price * (1 + _TakeProfitTriggerPercent / 100); if (price > trigger_price) { _TriggeredTakeProfit = true; // 触发回调止盈 _PeakPriceInPosition = price; // 记录价格高点 Log("多单已达到回调止盈的触发价格:", _N(trigger_price, 6), ", 当前价格:", _N(price, 6), ", 持仓价格:", _N(position[0].Price, 6)); } } } else if (position[0].Type == PD_SHORT) { // 空单持仓 if (_TriggeredTakeProfit) { // 已达到触发价格,监控是否止盈 _PeakPriceInPosition= price < _PeakPriceInPosition ? price : _PeakPriceInPosition; // 更新价格低点 if (_UsePositionRetracement) { take_profit_price = _PeakPriceInPosition + (position[0].Price - _PeakPriceInPosition) * (_CallBakcPercent / 100); // 计算回调的止盈价格 } else { take_profit_price = _PeakPriceInPosition * (1 + _CallBakcPercent / 100); // 计算回调的止盈价格 } if (price > take_profit_price) { coverShort(-1, position[0].Amount); // 平空 calculateProfit(ticker); _TriggeredTakeProfit = false; // 复位触发标记 _TrendWhenTakeProfitOrStopLoss = -1; // 记录止盈时候的趋势 _HadTakeProfit = true; // 记录发生了止盈 Log("空单回调止盈:持仓中价格低点:", _N(_PeakPriceInPosition, 6), ", 止盈价格:", _N(take_profit_price, 6), ", 当前价格:", _N(price, 6), ", 持仓价格:", _N(position[0].Price, 6), _EnableMessageSend ? "@" : "#FF1CAE"); } } else { // 监控是否达到回调止盈的触发价格 trigger_price = position[0].Price * (1 - _TakeProfitTriggerPercent / 100); if (price < trigger_price) { _TriggeredTakeProfit = true; // 触发回调止盈 _PeakPriceInPosition = price; // 记录价格低点 Log("空单已达到回调止盈的触发价格:", _N(trigger_price, 6), ", 当前价格:", _N(price, 6), ", 持仓价格:", _N(position[0].Price, 6)); } } } } } // 下单 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 ((_HadStopLoss || _HadTakeProfit) && _TrendWhenTakeProfitOrStopLoss == 1) { // 发生了止盈止损,并且止盈止损时候趋势为多,不再做多 return; } if (position_size > 0 && position_type == PD_SHORT) { coverShort(-1, position_size); calculateProfit(ticker); } else if (position_size > 0 && position_type == PD_LONG) { // 多单持仓,不重复下单 return; } else { // 没有持仓,如果是首次运行或者策略重启,需要等待价格穿过一次EMA均线才下单 if (_PriceCrossEMAStatus != 2) { return; } } if (isEnoughAssetToOrder(_OrderSize, ticker)) { openLong(-1, _OrderSize); _HadStopLoss = false; _HadTakeProfit = false; } else { throw "不够钱下单!"; } } else if (short) { // 趋势空 if ((_HadStopLoss || _HadTakeProfit) && _TrendWhenTakeProfitOrStopLoss == -1) { // 发生了止盈止损,并且止盈止损时候趋势为空,不再做空 return; } if (position_size > 0 && position_type == PD_LONG) { coverLong(-1, position_size); calculateProfit(ticker); } else if (position_size > 0 && position_type == PD_SHORT) { // 空单持仓,不重复下单 return; } else { // 没有持仓,如果是首次运行或者策略重启,需要等待价格穿过一次EMA均线才下单 if (_PriceCrossEMAStatus != 2) { return; } } if (isEnoughAssetToOrder(_OrderSize, ticker)) { openShort(-1, _OrderSize); _HadStopLoss = false; _HadTakeProfit = false; } else { throw "不够钱下单!"; } } } // 趋势策略 function trendStrategy() { var ticker = _C(exchange.GetTicker); var position = _C(exchange.GetPosition); var account = _C(exchange.GetAccount); var records = _C(exchange.GetRecords, _KLinePeriod * 60); if (position.length > 1) { Log(position); throw "同时有多空持仓!"; } // 策略交互 runCmd(); // 状态栏信息打印 printLogStatus(ticker, account, position); // 止损 stopLoss(position, ticker); // 止盈 takeProfit(position, ticker); // 回调止盈 trackingTakeProfit(position, ticker); // 按照K线周期运行策略 if (!runInKLinePeriod(records)) { return; } // 趋势判断和下单 var long = false; var short = false; [long, short] = trendJudgment(records); if (!_OnlyTrendJudgment) { order(long, short, position, ticker); } } // 状态栏信息打印 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) + "%", '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(forced_cover_up_price, 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); } if (_UseTakeProfit && _UseTrackingTakeProfit) { throw "止盈和回调止盈不能同时使用!"; } } // 设置合约 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); } // main function main() { setContract(); initDatas(); while (true) { trendStrategy(); Sleep(_Interval); } }
JKMCHEN신사님, 트렌드 전략은 유지되고 있습니까?
eth8888자, 이게 다중화폐를 운영하는 방법이 아닌가요?
와이티나스감사합니다.
마이케오이 글을 공유해 주셔서 감사합니다.
여름은 당신을 때리지 않습니다.이 글은 제 블로그에 올라와 있습니다.
여름은 당신을 때리지 않습니다.예, 동전입니다.