从TV的闹钟里发送的消息内容为: OpenLong 开多 OpenShort 开空 CloseLong 平多 CloseShort 平空
警报名称随便填写,消息内容就是上面的英文(只填英文,不要带空格和其他符号) 记得填写正确的Webhook URL
参考地址:https://www.fmz.com/bbs-topic/5533
说明:
从TV接收止损信号,但TV信号发送是在K棒结束之后,本脚本中的止损为防止插针设计; 止盈可以比TV的止盈大一些,大约0.25倍的样子(说的是小止盈0.75%那种)。
// @ts-check
////TradingView信号
////从TradingView接收开仓、平仓信号(OpenLong/CloseLong,OpenShort/CloseShort)执行开仓、平仓操作。
////记得填写正确的Webhook URL 参考地址: https://www.fmz.com/bbs-topic/5533
// 参数设置
// 基本设置
var _trade_currency = null; // 交易对
var _interval = Interval; // 程序运行周期
var _use_quarter = UseQuarter; // 季度合约,默认USDT永续合约
var _enable_message_send = EnableMessageSend; // 推送消息
// 下单设置
var _margin_level = MarginLevel; // 杠杆倍数
var _order_size = OrderSize; // 下单数量/张数
var _order_by_margin = OrderByMargin; // 根据下单保证金来确定下单数量
var _order_margin_percent = OrderMarginPercent; // 下单保证金百分比%(根据初始资金计算)
var _price_precision = PricePrecision; // 下单价格精度
var _amount_precision = AmountPrecision; // 下单数量精度
var _one_size_in_current_coin = OneSizeInCurrentCoin; // U本位合约中,一张ETH所代表的ETH数量
var _quarter_one_size_value = QuarterOneSizeValue; // 币本位合约中,一张ETH所代表的USDT数量
//// 止盈止损 ////
// 止损
var _STOPLOSS_PRICEPERCENT = StopLossPricePercent; // 止损价格百分比
// 挂单止盈
var _TAKEPROFIT_ORDER_OPEN = TakeProfit_OrderOpen // 挂单止盈开关
var _TAKEPROFIT_ORDER_PRICEPERCENT_1 = TakeProfit_Order_PricePercent_1; // 挂单止盈-1-价格百分比%
var _TAKEPROFIT_ORDER_AMOUNTPERCENT_1 = TakeProfit_Order_AmountPercent_1; // 挂单止盈-1-数量百分比%
var _TAKEPROFIT_ORDER_PRICEPERCENT_2 = TakeProfit_Order_PricePercent_2; // 挂单止盈-2-价格百分比%
var _TAKEPROFIT_ORDER_AMOUNTPERCENT_2 = TakeProfit_Order_AmountPercent_2; // 挂单止盈-2-数量百分比%
var _TAKEPROFIT_ORDER_PRICEPERCENT_3 = TakeProfit_Order_PricePercent_3; // 挂单止盈-2-价格百分比%
var _TAKEPROFIT_ORDER_AMOUNTPERCENT_3 = TakeProfit_Order_AmountPercent_3; // 挂单止盈-2-数量百分比%
var _TAKEPROFIT_ORDER_PRICEPERCENT_4 = TakeProfit_Order_PricePercent_4; // 挂单止盈-2-价格百分比%
var _TAKEPROFIT_ORDER_AMOUNTPERCENT_4 = TakeProfit_Order_AmountPercent_4; // 挂单止盈-2-数量百分比%
var _TAKEPROFIT_ORDER_PRICEPERCENT_5 = TakeProfit_Order_PricePercent_5; // 挂单止盈-2-价格百分比%
var _TAKEPROFIT_ORDER_AMOUNTPERCENT_5 = TakeProfit_Order_AmountPercent_5; // 挂单止盈-2-数量百分比%
//// 回调止盈 ////
// 固定回调
var _PULLBACK_FIXED_OPEN = PullbackFixedOpen; // 机制--是否启用固定回调止盈?
var _PULLBACK_FIXED_STARTPRICEPERCENT = PullbackFixedStartPricePercent; // 盈利达到多少开启固定回调
var _PULLBACK_FIXED_PRICEPERCENT_1 = PullbackFixedPricePercent_1; // 止盈回调点位1(回调百分比%),到达这个点位,减仓
var _PULLBACK_FIXED_AMOUNTPERCENT_1 = PullbackFixedAmountPercent_1; // 回调止盈点位1 的数量百分比
var _PULLBACK_FIXED_PRICEPERCENT_2 = PullbackFixedPricePercent_2; // 止盈回调点位2(回调百分比%),到达这个点位,减仓
// 利润回调
var _PULLBACK_PROFIT_OPEN = PullbackProfitOpen; // 机制--是否启用利润回调止盈?
var _PULLBACK_PROFIT_OPEN_2 = PullbackProfitOpen_2; // 机制--是否启用利润回调平仓?
var _PULLBACK_PROFIT_STARTPRICEPERCENT = PullbackProfitStartPricePercent; // 利润达到百分之多少,开始利润回调
//var _PULLBACK_PROFIT_PRICEPERCENT = PullbackProfitPricePercent; // 利润回调百分之多少,则减仓
var _PULLBACK_PROFIT_AMOUNTPERCEHT = PullbackProfitAmountPercent; // 利润回调减仓数量(当前持有仓位的百分之多少)
var _PULLBACK_PROFIT_MAXREPEATTIMES = PullbackProfitMaxRepeatTimes; // 最多执行多少次利润回调止盈
var _PULLBACK_PROFIT_MULT_1 = PullbackProfitMult_1; // 利润回调止盈乘数
var _PULLBACK_PROFIT_MULT_2 = PullbackProfitMult_2; // 利润回调平仓乘数
////运算变量
var _positions_type = null; // 用于挂单止盈之后的收益展示
var _OpenPositionsTime = 0; // 开仓时候的时间戳,用于限制回调止盈的在开仓时候出问题
// 止损
var _stoploss_price = 0; // 止损价格,用于止损运算
var _had_stoploss = false; // 已经达到止损价格
// 挂单止盈
var _takeprofit_order_price_1 = 0; // 挂单止盈价格-1
var _takeprofit_order_amount_1 = 0; // 挂单止盈数量-1
var _takeprofit_order_price_2 = 0; // 挂单止盈价格-2
var _takeprofit_order_amount_2 = 0; // 挂单止盈数量-2
var _takeprofit_order_price_3 = 0; // 挂单止盈价格-3
var _takeprofit_order_amount_3 = 0; // 挂单止盈数量-3
var _takeprofit_order_price_4 = 0; // 挂单止盈价格-4
var _takeprofit_order_amount_4 = 0; // 挂单止盈数量-4
var _takeprofit_order_price_5 = 0; // 挂单止盈价格-5
var _takeprofit_order_amount_5 = 0; // 挂单止盈数量-5
var _takeprofit_order_id_1 = null; // 记录止盈单ID
var _takeprofit_order_id_2 = null; // 记录止盈单ID
var _takeprofit_order_id_3 = null; // 记录止盈单ID
var _takeprofit_order_id_4 = null; // 记录止盈单ID
var _takeprofit_order_id_5 = null; // 记录止盈单ID
var _takeprofit_order_hastakeprofit_1 = false; // 是否止盈过? 用于打印收益信息
var _takeprofit_order_hastakeprofit_2 = false; // 是否止盈过? 用于打印收益信息
var _takeprofit_order_hastakeprofit_3 = false; // 是否止盈过? 用于打印收益信息
var _takeprofit_order_hastakeprofit_4 = false; // 是否止盈过? 用于打印收益信息
var _takeprofit_order_hastakeprofit_5 = false; // 是否止盈过? 用于打印收益信息
// 固定回调
var _pullback_fixed_startprice = 0; // 开关变量(监测回调止盈机制是否开始)-多
var _pullback_fixed_switch = false; // 标记多单回调止盈已开始
var _PEAK_PRICE_IN_POSITIONS = 0; // 持仓中价格的峰值点(最高/最低点)
var _pullbakc_fixed_price_1 = 0; // 多单回调止盈价格-1
var _pullbakc_fixed_price_2 = 0; // 多单回调止盈价格-2
var _pullback_fixed_hastakeprofit = false; // 已经止盈过,防止回调之后连续减仓
// 利润回调
var _pullback_profit_startprice = 0; // 在什么利润百分比的时候开启利润回调止盈
var _pullback_profit_switch = false; // 利润回调止盈开关
var _pullback_profit_switch_2 = false; // 利润回调平仓开关
var _PEAK_PROFIT_IN_POSITIONS = 0; // 持仓中盈利的峰值点(最高/最低点)
var _pullback_profit_price = 0; // 利润回调止盈的利润百分比
var _pullback_profit_price_2 = 0; // 利润回调平仓的利润百分比
var _pullback_profit_hastakeprofit = false; // 已经止盈过
var _pullback_profit_repeattimes = 0; // 计算变量,回调止盈一次,则 + 1
// 时间戳--防止过度执行
var _PULLBACK_SLEEPTIME = 0; // 纳秒级时间戳,在开单和平单时(2秒内)保证回调止盈函数不执行
// 统计变量
var _init_asset = 0; // 账户资产
var _profit_local = 0; // 利润
var _take_profit_count = 0; // 止盈次数
var _trade_count = 0; // 交易次数
var _strategy_run_time_stamp_string = "strategy_run_time"; // 策略运行时间
var _strategy_datas = { start_run_timestamp: 0, others: "" }; // 策略开始时间
var _user_datas = null; // 保存用户数据
var current_asset = 0; // 当前资产(改为全局变量为了保证开单的数量准确)
// 相对固定参数
var _maintenance_margin_rate = 0.004 // 维持保证金率
var _taker_fee = 0.0005; // 吃单手续费
var _is_USDT_standard = false; // USDT本位开单和结算
// 全局变量
var positions = null; // 从交易所获取的仓位信息
var account = null; // 从交易所获取的账户信息
var ticker = null; // 从交易所获取的市场行情
var _base_margin; // 初始杠杆
var _asset_precision = 0; // 资产精度
var _asset_price_precision = 0; // 价格精度
var DEFAULT_ASSET_PRECISION = 3; // 资产精度默认值
var DEFAULT_PRICE_PRECISION = 2; // 价格精度的默认值
var _has_open_long = false; // 跟踪是否已经开过多单
var _has_open_short = false; // 跟踪是否已经开过空单
var _TRIGGER_PULLBACK = false; // 是否触发了回调止盈
// 保存程序起始运行时间 秒级时间戳
function _SaveStrategyRunTime() {
var local_data_strategy_run_time = _G(_strategy_run_time_stamp_string);
if (local_data_strategy_run_time == null) {
_strategy_datas.start_run_timestamp = Unix();
_G(_strategy_run_time_stamp_string, _strategy_datas.start_run_timestamp);
}
else {
_strategy_datas.start_run_timestamp = local_data_strategy_run_time;
}
}
// 设置程序起始运行时间 秒级时间戳
function _SetStrategyRunTime(timestamp) {
_G(_strategy_run_time_stamp_string, timestamp);
_strategy_datas.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() {
_user_datas =
{
init_assets: _init_asset,
profit_local: _profit_local,
take_profit_count: _take_profit_count,
trade_count: _trade_count
};
// 存储到本地
_G(exchange.GetLabel(), _user_datas);
Log("已把所有数据保存到本地.");
}
// 读取用户本地数据,程序启动时候运行一次
function _ReadUserDataLocal(positions, account, ticker) {
var user_data = _G(exchange.GetLabel()); //从本地获取用户数据
if (user_data == null)
{//如果数据为空,则写入数据
_init_asset = _GetAccountAsset(positions, account, ticker);
_user_datas = {
init_assets: _init_asset, //账户资产
profit_local: 0, //账户利润
take_profit_count: 0, //获利次数
trade_count: 0 //交易次数
};
}
else
{//如果数据不为空,则从本地获取数据
_user_datas = user_data; //
}
Log("当前资金: ", _N(_GetAccountAsset(positions, account, ticker), 4));
}
// 清除用户本地数据,交互按钮点击运行
function _ClearUserDataLocal()
{
_G(exchange.GetLabel(), null);
Log(exchange.GetLabel(), ": 已清除本地数据.");
}
//将购买数量调整为合适的精度:
function _FixAmountPrecision(_amount, _amount_precision)
{
return parseFloat(_amount.toFixed(_amount_precision));
}
// 将价格调整到合适的精度
function _FixPricePrecision(_price, _price_precision)
{
return parseFloat(_price.toFixed(_price_precision));
}
// 状态栏信息打印
function _PrintLogStatus(positions, account, ticker) {
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 the_running_days = _GetDaysFromTimeStamp(_strategy_datas.start_run_timestamp, Unix());
var monthly_rate_of_profit = 0;
if (the_running_days > 1)
monthly_rate_of_profit = _profit_local / _init_asset / the_running_days * 30;
table_overview.rows.push([
_D(_strategy_datas.start_run_timestamp * 1000), //开始时间
the_running_days, //已运行天数
_trade_count, //交易次数
_trade_count == 0 ? 0 : (_N(_take_profit_count / _trade_count * 100, 2) + "%"), //胜率
_N(monthly_rate_of_profit * 100, 2) + "%", //预估月化%
_N(monthly_rate_of_profit * 12 * 100, 2) + "%", //预估年化%
]);
// 账户资金打印
current_asset = _GetAccountAsset(positions, account, ticker); //获取账户资产
var max_order_size = _GetMaxOrderSize(positions, account, ticker, _margin_level); //获取可开单张数
var asset_profit = current_asset - _init_asset;
var asset_profit_percent = asset_profit / _init_asset;
table_account.rows.push([
_N(current_asset, 4), //当前资产
_N(_init_asset, 4), //初始资产
_N(_is_USDT_standard ? account.Balance : account.Stocks, 4), //可用余额
_N(_is_USDT_standard ? account.FrozenBalance : account.FrozenStocks, 4), //冻结余额
max_order_size, //可下单张数
_N(asset_profit, 4), //收益
_N(asset_profit_percent * 100, 2) + "%" //收益百分比
]);
// 持仓情况打印
var positions_direction = ""; // 持仓方向
var positions_profit_percent = 0; // 浮盈百分比
var positions_profit = 0; // 浮盈
var positions_margin = 0; // 保证金
if (positions.length == 0)
{// 未持仓
table_position.rows.push(["无持仓", "-", "-", "-", "-", "-", "-", "-", "-", "-"]);
}
else
{// 持仓状态
positions_direction = positions[0].Type == PD_LONG ? "多单" : "空单";
[positions_profit, positions_profit_percent] = _GetSinglepositionsProfit(positions, account, ticker); //获取当前利润
positions_margin = _GetSinglepositionsMargin(positions, account, ticker); //获取当前仓位保证金
table_position.rows.push([
exchange.GetCurrency(), // 交易币种
_margin_level + "倍 / " + positions_direction, // 杠杆倍数 + 方向
positions[0].Amount, // 数量
_N(positions_margin, 4), // 保证金
_N(positions_profit, 4), // 浮动盈亏
_N((positions_profit_percent * 100), 2) + "% / " + _N(_PEAK_PROFIT_IN_POSITIONS, 2) + "% / " + _N(_pullback_profit_price, 2) + " % /" + _N(_pullback_profit_price_2, 2) + " %", // 浮动盈亏 + 最大盈利 + 利润回调止盈 + 利润回调平仓
_N(positions[0].Price, 4) + " / " + _N(ticker.Last, 4), // 持仓均价 + 当前价格
_N(_stoploss_price, 4), // 止损价格
_N(_takeprofit_order_price_1, 4) + " / " + _N(_takeprofit_order_price_2, 4) + " / " + _N(_takeprofit_order_price_3, 4) + " / " + _N(_takeprofit_order_price_4, 4) + " / " + _N(_takeprofit_order_price_5, 4), // 挂单止盈价格
_N(_pullbakc_fixed_price_1, 4) + " / " + _N(_pullbakc_fixed_price_2, 4), // 回调止盈 点位1价格 / 点位2 价格
]);
}
// 打印表格
LogStatus(
'`' + JSON.stringify(table_overview) + '`\n'
+ '`' + JSON.stringify(table_account) + '`\n'
+ '`' + JSON.stringify(table_position) + '`\n');
}
// 初始化数据
function _InitDatas(positions, account, ticker) {
_SaveStrategyRunTime();
_ReadUserDataLocal(positions, account, ticker);
_init_asset = _user_datas.init_assets; //资产统计
_profit_local = _user_datas.profit_local; //统计收益
_take_profit_count = _user_datas.take_profit_count; //盈利次数
_trade_count = _user_datas.trade_count; //交易次数
current_asset = _GetAccountAsset(positions, account, ticker) // 统计当前资产
if (_order_by_margin)
{
_GetRealOrderSize(-1, _order_size);
Log("已经重新计算下单张数: ", _order_size);
}
}
// 获取账户资产
function _GetAccountAsset(positions, account, ticker) {
// 计算不同情况下的账户初始资产
var account_asset = 0;
var positions_margin = _GetSinglepositionsMargin(positions, account, ticker);
if (_is_USDT_standard)
{// U本位资产统计
if (positions.length > 0)
{// 持仓时
account_asset = account.Balance + account.FrozenBalance + positions_margin; // 资产 = 未锁定资产 + 锁定资产 + 仓位保证金
}
else
{// 空仓时
account_asset = account.Balance + account.FrozenBalance; // 资产 = 未锁定资产 + 锁定资产
}
}
else
{// 币本位资产统计
if (positions.length > 0)
{// 持仓位时
account_asset = account.Stocks + account.FrozenStocks + positions_margin; // 资产 = 未锁定资产 + 锁定资产 + 仓位保证金
}
else
{// 空仓时
account_asset = account.Stocks + account.FrozenStocks; // 资产 = 未锁定资产 + 锁定资产
}
}
return account_asset;
}
// 策略交互
function _RunCommand(command) {
var positions = _C(exchange.GetPositions); //获取当前交易所账户的持仓信息,并返回一个包含持仓信息的对象。
var account = _C(exchange.GetAccount); //获取交易所账户信息
var ticker = _C(exchange.GetTicker); //获取当前交易对的市场行情信息
if (command.indexOf("FMZ_ClearLocalData") == 0) {
// 清除本地数据
_ClearUserDataLocal();
}
else if (command.indexOf("FMZ_SaveLocalData") == 0) {
// 保存数据到本地
_SaveUserDatasLocal();
}
else if (command.indexOf("FMZ_ClearLog") == 0) {
// 清除日志
LogReset(Number(3));
Log("只保留3条日志,其他清除。")
}
else if (command.indexOf("FMZ_OrderSize:") == 0) {
// 修改下单张数
if (_order_by_margin) {
Log("已经使用保证金数量来下单,无法直接修改下单数量!");
} else {
var FMZ_order_size = Number(command.replace("FMZ_OrderSize:", ""));
_order_size = FMZ_order_size;
Log("下单张数已经修改为: ", _order_size);
}
}
else if (command.indexOf("FMZ_OrderMarginPercent:") == 0) {
// 修改下单保证金百分比
if (_order_by_margin) {
var order_margin_percent = Number(command.replace("FMZ_OrderMarginPercent:", ""));
_order_margin_percent = order_margin_percent;
Log("下单保证金百分比: ", _order_margin_percent, "%");
} else {
Log("没有打开根据保证金数量下单,无法修改下单保证金百分比!");
}
}
else if (command.indexOf("FMZ_OpenLong") == 0) {// 手动开多
if (positions.length > 0 && positions[0].Type === PD_LONG) {
Log("持有多仓,无法继续开仓");
}
else
{
_OpenPositions(1, 0, positions, account, ticker);
}
}
else if (command.indexOf("FMZ_OpenShort") == 0) {// 手动开空
if (positions.length > 0 && positions[0].Type === PD_SHORT) {
Log("持有空仓,无法继续开仓");
}
else
{
_OpenPositions(0, 1, positions, account, ticker);
}
}
else if (command.indexOf("FMZ_CloseLong") == 0) {// 手动平多
if (positions.length > 0) {
if (positions[0].Type === PD_LONG) {
_Cover_1(); // 快速平仓
_ResetVariables(); // 重置运算变量
_CalculateProfit(positions, account, ticker); // 统计收益
} else {
Log("当前持有空头仓位");
}
}
else {
Log("没有持仓,无法平多");
}
}
else if (command.indexOf("FMZ_CloseShort") == 0) {//手动平空
if (positions.length > 0) {
if (positions[0].Type === PD_SHORT) {
_Cover_1(); // 快速平仓
_ResetVariables(); // 重置运算变量
_CalculateProfit(positions, account, ticker); // 统计收益
} else {
Log("当前持有多头持仓");
}
} else {
Log("没有持仓,无法平空");
}
}
}
// 重新计算下单数量
function _GetRealOrderSize(price, amount)
{
var ticker = _C(exchange.GetTicker)
var real_price = price == -1 ? ticker.Last : price;
//var asset = _N(_GetAccountAsset(positions, account, ticker), 4) //删除,为了保证开单数量的准确性换用 current_asset
if (_order_by_margin)//如果按照保证金百分比下单
{
if (_is_USDT_standard) {
_order_size = _N(current_asset * (_order_margin_percent / 100) / real_price * _margin_level / _one_size_in_current_coin, _amount_precision);
} else {
_order_size = _N(current_asset * (_order_margin_percent / 100) * _margin_level * real_price / _quarter_one_size_value, _amount_precision);
}
}
else
{//如果按照用户输入订单数下单
_order_size = amount;
}
Log("可开单数量:" + _order_size);
return _order_size;
}
// 获取单向持仓的收益和收益%
function _GetSinglepositionsProfit(positions, account, ticker) {
if (positions.length == 0)
return [0, 0];
var price = ticker.Last;
var positions_margin = _GetSinglepositionsMargin(positions, account, ticker);
var positions_profit_percent = positions[0].Type == PD_LONG ? ((price - positions[0].Price) / positions[0].Price) * _margin_level : ((positions[0].Price - price) / positions[0].Price) * _margin_level;
var positions_profit = positions_margin * positions_profit_percent;
return [positions_profit, positions_profit_percent];
}
// 计算最大可下单张数
function _GetMaxOrderSize(positions, account, ticker, margin_level)
{
var max_order_size = 0;
if (_is_USDT_standard) {
max_order_size = account.Balance * margin_level / (_one_size_in_current_coin * ticker.Last);
} else {
max_order_size = account.Stocks * ticker.Last / _quarter_one_size_value * margin_level;
}
return _N(max_order_size, _amount_precision);
}
// 获取单个持仓占用保证金
function _GetSinglepositionsMargin(positions, account, ticker)
{
var positions_margin = 0;
if (positions.length > 0)
{
if (_is_USDT_standard) {
positions_margin = positions[0].Amount * _one_size_in_current_coin * ticker.Last / _margin_level;
} else {
positions_margin = positions[0].Amount * _quarter_one_size_value / ticker.Last / _margin_level;
}
}
return positions_margin;
}
//// 设置合约
function _SetContract(trade_currency)
{
_is_USDT_standard = _trade_currency.includes("USDT") ? true : false;
if (!IsVirtual()) {
// 实盘设置
exchange.SetCurrency(_trade_currency);
if (_use_quarter) {
exchange.SetContractType("quarter");
} else {
exchange.SetContractType("swap");
}
} else {
// 回测设置
if (_is_USDT_standard) {
exchange.SetContractType("swap");
} else {
exchange.SetContractType("quarter");
}
}
//////////通过交易对手动解析数量精度//////////////////////////////////////
var ticker = _C(exchange.GetTicker)
// 获取交易对信息
if (ticker)
{//通过Ticker,尝试手动解析精度
var priceString = ticker.Last.toString();
_price_precision = (priceString.split(".")[1] || "").length;
Log("推测的价格精度: ", _price_precision);
}
else
{
Log("无法获取到交易对 ", trade_currency, " 的精度信息, 请手动设定");
}
//////////通过市场买单手动解析数量精度//////////////////////////////////////
var depth = _C(exchange.GetDepth);
var totalPrecision = 0;
var sampleCount = 0;
if (depth && depth.Bids.length > 0) {
for (var i = 0; i < depth.Bids.length; i++) {
var amountString = depth.Bids[i].Amount.toString();
totalPrecision += (amountString.split(".")[1] || "").length;
sampleCount++;
}
if (sampleCount > 0) {
_amount_precision = Math.round(totalPrecision / sampleCount);
Log("解析的数量精度: ", _amount_precision);
}
} else {
Log("无法获取到交易对 ", trade_currency, " 的数量精度信息, 请手动设定");
}
//////////通过市场买单手动解析数量精度//////////////////////////////////////
exchange.SetMarginLevel(_margin_level);
exchange.SetPrecision(_price_precision, _amount_precision);
}
// 是否还够资金下单
function _IsEnoughAssetToOrder(order_size, positions, account, ticker)
{
var is_enough = true;
var account = _C(exchange.GetAccount);
if (_is_USDT_standard) {
if (account.Balance < order_size * ticker.Last * _one_size_in_current_coin / _margin_level)
{
is_enough = false;
}
} else {
if (account.Stocks < order_size * _quarter_one_size_value / ticker.Last / _margin_level)
{
is_enough = false;
}
}
return is_enough;
}
//// 检查重启后是否存在多单或空单
function _Initialize(positions) {
// 撤销重启之前的所有挂单
_CancelAllOrders();
// 检查重启后是否持有多单或空单,调整止损价格,并重新根据止盈价格挂止盈单
//var positions = exchange.GetPositions();
for (var i = 0; i < positions.length; i++) {
if (positions[i].Type === PD_LONG || positions[i].Type === PD_LONG_YD) {
_has_open_long = true;
_positions_type = "Long"; // 记录订单方向,用于止盈
// 止损-多
_stoploss_price = _FixPricePrecision(positions[0].Price * (1 - _STOPLOSS_PRICEPERCENT / 100), _price_precision); // 更新止损价格
// 固定回调
_pullback_fixed_startprice = positions[0].Price * (1 + _PULLBACK_FIXED_STARTPRICEPERCENT / 100); // 更新开关变量
_pullbakc_fixed_price_1 = 0; // 更新止盈回调价格
_pullbakc_fixed_price_2 = 0; // 更新止盈回调价格
_pullback_fixed_switch = false; // 标记多单回调止盈已开始
_pullback_fixed_hastakeprofit = false; // 已经止盈过,防止回调之后连续减仓
// 利润回调
_pullback_profit_startprice = positions[0].Price * (1 + _PULLBACK_PROFIT_STARTPRICEPERCENT / 100); // 更新开关变量
_pullback_profit_price = 0; // 更新利润回调止盈价格
_pullback_profit_price_2 = 0; // 更新利润回调平仓价格
_pullback_profit_switch = false; // 关闭利润回调止盈开关
_pullback_profit_switch_2 = false; // 关闭利润回调平仓开关
_pullback_profit_hastakeprofit = false; // 是否已经止盈过
_pullback_profit_repeattimes = 0; // 计算变量,回调止盈一次,则 + 1
// 打印信息-多
Log("存在多单, 持仓价格: ", positions[0].Price, ", 止损价格: ", _N(_stoploss_price, 6)); //输出开仓价格信息////输出开仓价格信息
// 挂止盈单
if(_TAKEPROFIT_ORDER_OPEN)
{
_MakeTakeProfitOrder(positions);
}
}
else if (positions[i].Type === PD_SHORT || positions[i].Type === PD_SHORT_YD) {
_has_open_short = true;
_positions_type = "Short"; // 记录订单方向,用于止盈
// 止损
_stoploss_price = _FixPricePrecision(positions[0].Price * (1 + _STOPLOSS_PRICEPERCENT / 100), _price_precision); //更新止损价格
// 固定回调
_pullback_fixed_startprice = positions[0].Price * (1 - _PULLBACK_FIXED_STARTPRICEPERCENT / 100); // 开关变量
_pullbakc_fixed_price_1 = 0; // 更新止盈回调价格
_pullbakc_fixed_price_2 = 0; // 更新止盈回调价格
_pullback_fixed_switch = false; // 标记多单回调止盈已开始
_pullback_fixed_hastakeprofit = false; // 已经止盈过,防止回调之后连续减仓
// 利润回调
_pullback_profit_startprice = positions[0].Price * (1 - _PULLBACK_PROFIT_STARTPRICEPERCENT / 100); // 开关变量
_pullback_profit_price = 0; // 更新利润回调止盈价格
_pullback_profit_price_2 = 0; // 更新利润回调平仓价格
_pullback_profit_switch = false; // 关闭利润回调止盈开关
_pullback_profit_switch_2 = false; // 关闭利润回调平仓开关
_pullback_profit_hastakeprofit = false; // 是否已经止盈过
_pullback_profit_repeattimes = 0; // 计算变量,回调止盈一次,则 + 1
////输出开仓价格信息
Log("存在空单, 持仓价格: ", positions[0].Price, ", 止损价格: ", _N(_stoploss_price, 6)); //输出开仓价格信息
// 挂止盈单
if(_TAKEPROFIT_ORDER_OPEN)
{
_MakeTakeProfitOrder(positions);
}
}
}
}
//// 根据TV消息执行对应的操作
function _RunTVCommand(command)
{
////
var positions = _C(exchange.GetPositions); //获取当前交易所账户的持仓信息,并返回一个包含持仓信息的对象。
var account = _C(exchange.GetAccount); //获取交易所账户信息
var ticker = _C(exchange.GetTicker); //获取当前交易对的市场行情信息
var action = command.Action; //获取要执行的处理
if (positions.length > 1) { ////如果同时持有多空仓位则退出
Log(positions);
throw "同时有多空持仓!无法操作";
}
switch (action) {
case "OpenLong": // 开多单
_OpenPositions(1, 0, positions, account, ticker);
break;
case "OpenShort": // 开空单
_OpenPositions(0, 1, positions, account, ticker);
break;
case "CloseLong": // TV信号平多
if (positions.length > 0) {
if (positions[0].Type === PD_LONG) {
_Cover_1(); // 快速平仓
_ResetVariables(); // 重置运算变量
_CalculateProfit(positions, account, ticker); // 统计收益
} else {
Log("当前持有空头仓位");
}
}
else {
Log("没有持仓,无法平多");
}
break;
case "CloseShort": //TV信号平空
if (positions.length > 0) {
if (positions[0].Type === PD_SHORT) {
_Cover_1(); // 快速平仓
_ResetVariables(); // 重置运算变量
_CalculateProfit(positions, account, ticker); // 统计收益
} else {
Log("当前持有多头持仓");
}
} else {
Log("没有持仓,无法平空");
}
break;
default:
break;
}
}
//// 根据订单方向下单
function _OpenPositions(long, short, positions, account, ticker)
{
var positions_size = positions.length > 0 ? positions[0].Amount : 0;
var positions_type = positions.length > 0 ? positions[0].Type : null;
if (long)////开多单
{
//判断是否持仓
if (positions_size > 0 && positions_type == PD_SHORT) { // 如果当前持有空仓
_Cover_1(); // 快速平仓
_ResetVariables(); // 重置运算变量
_CalculateProfit(positions, account, ticker); // 统计收益
}
else if (positions_size > 0 && positions_type == PD_LONG) { // 如果当前持有多仓
Log("持有多单,不继续开多."); // 多单持仓,不重复下单
return;
}
else { }
// 如果资金充足,则下单
if (_IsEnoughAssetToOrder(_order_size, positions, account, ticker))
{
_OpenLong(-1, _order_size); // 开多单
Sleep(2000); // 等待一会儿
var positions = _C(exchange.GetPositions)
if (positions.length > 0) {
_has_open_long = true;
_positions_type = "Long"; // 记录订单方向,用于止盈
// 止损-多
_stoploss_price = _FixPricePrecision(positions[0].Price * (1 - _STOPLOSS_PRICEPERCENT / 100), _price_precision); // 更新止损价格
// 固定回调
_pullback_fixed_startprice = positions[0].Price * (1 + _PULLBACK_FIXED_STARTPRICEPERCENT / 100); // 更新开关变量
_pullbakc_fixed_price_1 = 0; // 更新止盈回调价格
_pullbakc_fixed_price_2 = 0; // 更新止盈回调价格
_pullback_fixed_switch = false; // 标记多单回调止盈已开始
_pullback_fixed_hastakeprofit = false; // 已经止盈过,防止回调之后连续减仓
// 利润回调
_pullback_profit_startprice = positions[0].Price * (1 + _PULLBACK_PROFIT_STARTPRICEPERCENT / 100); // 更新开关变量
_pullback_profit_price = 0; // 更新利润回调止盈价格
_pullback_profit_price_2 = 0; // 更新利润回调平仓价格
_pullback_profit_switch = false; // 关闭利润回调止盈开关
_pullback_profit_switch_2 = false; // 关闭利润回调平仓开关
_pullback_profit_hastakeprofit = false; // 是否已经止盈过
_pullback_profit_repeattimes = 0; // 计算变量,回调止盈一次,则 + 1
// 打印信息
Log("市价开多, 价格: ", positions[0].Price, ", 止损价格: ", _N(_stoploss_price, 6), ", 止盈价格:" + _N(_takeprofit_order_price_1, 6) + " / "+ _N(_takeprofit_order_price_2, 6)); //输出开仓价格信息////输出开仓价格信息
// 挂止盈单
if (_TAKEPROFIT_ORDER_OPEN)
{
_MakeTakeProfitOrder(positions);
}
}
else {
Log("开多单失败。")
}
}
else // 资金不足
{
throw "保证金不足!";
}
}
else if (short) // 开空单
{
////判断是否持仓
if (positions_size > 0 && positions_type == PD_LONG) { //如果当前持有多仓
_Cover_1(); // 快速平仓
_ResetVariables(); // 重置运算变量
_CalculateProfit(positions, account, ticker); //统计收益
}
else if (positions_size > 0 && positions_type == PD_SHORT) {
Log("持有空单,不继续开空"); // 空单持仓,不重复下单
return;
}
else { }
//// 如果资金充足,则下单
if (_IsEnoughAssetToOrder(_order_size, positions, account, ticker))
{
_OpenShort(-1, _order_size); //开空单
Sleep(2000); // 等待一会儿
var positions = _C(exchange.GetPositions)
if (positions.length > 0) {
_has_open_short = true;
_positions_type = "Short"; // 记录订单方向,用于止盈
// 止损
_stoploss_price = _FixPricePrecision(positions[0].Price * (1 + _STOPLOSS_PRICEPERCENT / 100), _price_precision); //更新止损价格
// 固定回调
_pullback_fixed_startprice = positions[0].Price * (1 - _PULLBACK_FIXED_STARTPRICEPERCENT / 100); // 开关变量
_pullbakc_fixed_price_1 = 0; // 更新止盈回调价格
_pullbakc_fixed_price_2 = 0; // 更新止盈回调价格
_pullback_fixed_switch = false; // 标记多单回调止盈已开始
_pullback_fixed_hastakeprofit = false; // 已经止盈过,防止回调之后连续减仓
// 利润回调
_pullback_profit_startprice = positions[0].Price * (1 - _PULLBACK_PROFIT_STARTPRICEPERCENT / 100); // 开关变量
_pullback_profit_price = 0; // 更新利润回调止盈价格
_pullback_profit_price_2 = 0; // 更新利润回调平仓价格
_pullback_profit_switch = false; // 关闭利润回调止盈开关
_pullback_profit_switch_2 = false; // 关闭利润回调平仓开关
_pullback_profit_hastakeprofit = false; // 是否已经止盈过
_pullback_profit_repeattimes = 0; // 计算变量,回调止盈一次,则 + 1
////输出开仓价格信息
Log("存在空单, 持仓价格: ", positions[0].Price, ", 止损价格: ", _N(_stoploss_price, 6)); //输出开仓价格信息
// 挂止盈单
if (_TAKEPROFIT_ORDER_OPEN)
{
_MakeTakeProfitOrder(positions);
}
}
else {
Log("开空单失败。")
}
}
else // 资金不足
{
throw "保证金不足!";
}
}
}
//开多
function _OpenLong(price, amount)
{
_ResetVariables(); // 重置运算变量
_positions_type = "Long"; // 更新订单方向
return _OrderDirectly("buy", price, _order_size);
}
// 开空
function _OpenShort(price, amount)
{
_ResetVariables(); // 重置运算变量
_positions_type = "Short"; // 更新订单方向
return _OrderDirectly("sell", price, _order_size);
}
// 平多(市价减仓)
function _ReduceLong(price, amount)
{
var positions = _C(exchange.GetPositions);
if (amount > 0)
{
if(positions[0].Amount < amount)
{
return _OrderDirectly("closebuy", price, positions[0].Amount);
}
else
{
return _OrderDirectly("closebuy", price, amount);
}
}
else
{
return null;
}
}
//平空(市价减仓)
function _ReduceShort(price, amount)
{//平仓空单
var positions = _C(exchange.GetPositions);
if (amount > 0)
{
if(positions[0].Amount < amount)
{
return _OrderDirectly("closesell", price, positions[0].Amount);
}
else
{
return _OrderDirectly("closesell", price, amount);
}
}
else
{
return null;
}
}
//// 平空(市价全平)
function _Cover_1() //止损平仓--只求速度
{
var positions = _C(exchange.GetPositions);
if (positions.length > 0 && positions[0].Type == PD_LONG)
{
return _OrderDirectly("closebuy", -1, positions[0].Amount);
}
else if (positions.length > 0 && positions[0].Type == PD_SHORT)
{
return _OrderDirectly("closesell", -1, positions[0].Amount);
}
else
{return null;}
}
function _ResetVariables() //止损平仓--重置运算变量
{
////重置运算变量
_order_size = _GetRealOrderSize(-1, _order_size);
////运算变量
_positions_type = null; // 用于挂单止盈之后的收益展示
// 止损
_stoploss_price = 0; // 止损价格,用于止损运算
_had_stoploss = false; // 已经达到止损价格
// 挂单止盈
_takeprofit_order_price_1 = 0; // 挂单止盈价格-1
_takeprofit_order_amount_1 = 0; // 挂单止盈数量-1
_takeprofit_order_price_2 = 0; // 挂单止盈价格-2
_takeprofit_order_amount_2 = 0; // 挂单止盈数量-2
_takeprofit_order_price_3 = 0; // 挂单止盈价格-3
_takeprofit_order_amount_3 = 0; // 挂单止盈数量-3
_takeprofit_order_price_4 = 0; // 挂单止盈价格-4
_takeprofit_order_amount_4 = 0; // 挂单止盈数量-4
_takeprofit_order_price_5 = 0; // 挂单止盈价格-5
_takeprofit_order_amount_5 = 0; // 挂单止盈数量-5
_takeprofit_order_id_1 = null; // 记录止盈单ID
_takeprofit_order_id_2 = null; // 记录止盈单ID
_takeprofit_order_id_3 = null; // 记录止盈单ID
_takeprofit_order_id_4 = null; // 记录止盈单ID
_takeprofit_order_id_5 = null; // 记录止盈单ID
_takeprofit_order_price_1 = 0; // 重置止盈价格1
_takeprofit_order_price_2 = 0; // 重置止盈价格2
_takeprofit_order_price_3 = 0; // 重置止盈价格3
_takeprofit_order_price_4 = 0; // 重置止盈价格4
_takeprofit_order_price_5 = 0; // 重置止盈价格5
_takeprofit_order_hastakeprofit_1 = false; // 是否止盈过? 用于打印收益信息
_takeprofit_order_hastakeprofit_2 = false; // 是否止盈过? 用于打印收益信息
_takeprofit_order_hastakeprofit_3 = false; // 是否止盈过? 用于打印收益信息
_takeprofit_order_hastakeprofit_4 = false; // 是否止盈过? 用于打印收益信息
_takeprofit_order_hastakeprofit_5 = false; // 是否止盈过? 用于打印收益信息
// 固定回调
_pullback_fixed_startprice = 0; // 开关变量(监测回调止盈机制是否开始)-多
_pullback_fixed_switch = false; // 标记多单回调止盈已开始
_PEAK_PRICE_IN_POSITIONS = 0; // 持仓中价格的峰值点(最高/最低点)
_pullbakc_fixed_price_1 = 0; // 多单回调止盈价格-1
_pullbakc_fixed_price_2 = 0; // 多单回调止盈价格-2
_pullback_fixed_hastakeprofit = false; // 已经止盈过,防止回调之后连续减仓
// 利润回调
_pullback_profit_startprice = 0; // 在什么利润百分比的时候开启利润回调止盈
_pullback_profit_switch = false; // 是否开始进行回调止盈
_pullback_profit_switch_2 = false; // 关闭利润回调平仓
_PEAK_PROFIT_IN_POSITIONS = 0; // 持仓中价格的峰值点(最高/最低点)
_pullback_profit_price = 0; // 利润回调减仓的利润值
_pullback_profit_price_2 = 0; // 利润回调平仓的利润值
_pullback_profit_hastakeprofit = false; // 已经止盈过
_pullback_profit_repeattimes = 0; // 计算变量,回调止盈一次,则 + 1
}
//// 平多(市价全平)
//function _CoverLong()
//{
// var positions = _C(exchange.GetPositions);
// _CancelAllOrders(); //取消所有挂单
// if (positions.length > 0 && positions[0].Type == PD_LONG)
// {
// return _OrderDirectly("closebuy", -1, positions[0].Amount);
// }
// else
// {return null;}
//}
//// 平空(市价全平)
//*function _CoverShort()
//{// 平仓空单
// var positions = _C(exchange.GetPositions);
// _CancelAllOrders(); //取消所有挂单
//
// if (positions.length > 0 && positions[0].Type == PD_SHORT)
// {
// return _OrderDirectly("closesell", -1, positions[0].Amount);
// }
// else
// {return null;}
//}
// 交易函数
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("多单市价平仓, 数量: ", amount);
}
else if(distance == "closesell")
{//市价平空
tradeFunc = exchange.Buy;
Log("空单市价平仓, 数量: ", amount);
}
exchange.SetDirection(distance);
return tradeFunc(price, amount);
}
function _CancelAllOrders() {
while (true) {
var orders = exchange.GetOrders(); // 获取当前所有挂单
if (!orders || orders.length === 0) {
break; // 如果没有挂单,就退出循环
}
for (var i = 0; i < orders.length; i++) {
exchange.CancelOrder(orders[i].Id); // 取消每一个挂单
Log("取消挂单: ", orders[i].Id); // 记录取消的挂单
Sleep(10); // 等待,防止请求过于频繁
}
}
}
//// 仓位监测,进行止盈止损和回调止盈
function _PositionMonitoring()
{
////这里必须要重新获取仓位、账户、市场信息,否则会报错
var positions = _C(exchange.GetPositions); //获取当前交易所账户的持仓信息,并返回一个包含持仓信息的对象。
var account = _C(exchange.GetAccount); //获取交易所账户信息
var ticker = _C(exchange.GetTicker); //获取当前交易对的市场行情信息
_PrintLogStatus(positions, account, ticker); // 状态栏信息打印
// 监控止损
if (_stoploss_price > 0) { // 如果止损价格不为空
_StopLoss(positions, account, ticker); // 调用对应函数
}
// 监控挂单止盈是否成交
// 如果机制开启了,并且持有仓位,并且某一个挂单止盈价格不为空
if (_TAKEPROFIT_ORDER_OPEN && (_takeprofit_order_price_1 > 0 || _takeprofit_order_price_2 > 0 || _takeprofit_order_price_3 > 0 || _takeprofit_order_price_4 > 0 || _takeprofit_order_price_5 > 0))
{
_TakeProfit(positions, account, ticker); // 调用对应函数
}
positions = _C(exchange.GetPositions); //重新获取仓位信息,防止监控时出现仓位为0的问题
// 监控固定回调止盈
if (_PULLBACK_FIXED_OPEN && positions.length > 0) { // 如果持有仓位,且启用了固定回调止盈机制
_PullbackTakeProfit_Fixed(positions, account, ticker); // 调用对应函数
}
// 监控利润回调止盈
if (_PULLBACK_PROFIT_OPEN && positions.length > 0) { // 如果持有仓位,且启用了利润回调止盈机制
_PullbackTakeProfit_Profit(positions, account, ticker); // 调用对应函数
}
}
// 挂空单止盈单
function _MakeTakeProfitOrder(positions) {
if (_TAKEPROFIT_ORDER_OPEN && _positions_type == "Long" || positions[0].Type === PD_LONG) {
// 挂单止盈-多
_takeprofit_order_price_1 = _FixPricePrecision(positions[0].Price * (1 + _TAKEPROFIT_ORDER_PRICEPERCENT_1 / 100), _price_precision); // 止盈价格-1
_takeprofit_order_amount_1 = _FixAmountPrecision(positions[0].Amount * _TAKEPROFIT_ORDER_AMOUNTPERCENT_1 / 100, _amount_precision); // 止盈数量-1
_takeprofit_order_price_2 = _FixPricePrecision(positions[0].Price * (1 + _TAKEPROFIT_ORDER_PRICEPERCENT_2 / 100), _price_precision); // 止盈价格-2
_takeprofit_order_amount_2 = _FixAmountPrecision(positions[0].Amount * _TAKEPROFIT_ORDER_AMOUNTPERCENT_2 / 100, _amount_precision); // 止盈数量-2
_takeprofit_order_price_3 = _FixPricePrecision(positions[0].Price * (1 + _TAKEPROFIT_ORDER_PRICEPERCENT_3 / 100), _price_precision); // 止盈价格-3
_takeprofit_order_amount_3 = _FixAmountPrecision(positions[0].Amount * _TAKEPROFIT_ORDER_AMOUNTPERCENT_3 / 100, _amount_precision); // 止盈数量-3
_takeprofit_order_price_4 = _FixPricePrecision(positions[0].Price * (1 + _TAKEPROFIT_ORDER_PRICEPERCENT_4 / 100), _price_precision); // 止盈价格-4
_takeprofit_order_amount_4 = _FixAmountPrecision(positions[0].Amount * _TAKEPROFIT_ORDER_AMOUNTPERCENT_4 / 100, _amount_precision); // 止盈数量-4
_takeprofit_order_price_5 = _FixPricePrecision(positions[0].Price * (1 + _TAKEPROFIT_ORDER_PRICEPERCENT_5 / 100), _price_precision); // 止盈价格-5
_takeprofit_order_amount_5 = _FixAmountPrecision(positions[0].Amount * _TAKEPROFIT_ORDER_AMOUNTPERCENT_5 / 100, _amount_precision); // 止盈数量-5
_takeprofit_order_hastakeprofit_1 = false; // 标记止盈,防止信息重复发送
_takeprofit_order_hastakeprofit_2 = false; // 标记止盈,防止信息重复发送
_takeprofit_order_hastakeprofit_3 = false; // 标记止盈,防止信息重复发送
_takeprofit_order_hastakeprofit_4 = false; // 标记止盈,防止信息重复发送
_takeprofit_order_hastakeprofit_5 = false; // 标记止盈,防止信息重复发送
// 挂多单止盈单-1
try {
Log("多 --> 挂止盈单-1,价格: ", _takeprofit_order_price_1, ", 数量: ", _takeprofit_order_amount_1); // 输出日志
exchange.SetDirection("closebuy"); // 设置止盈平多交易方向
_takeprofit_order_id_1 = exchange.Sell(_takeprofit_order_price_1, _takeprofit_order_amount_1); // 挂止盈单
}
catch (error) {
Log("多 --> 挂止盈单-1,失败: ", error.message, "错误详情: ", error);
_takeprofit_order_id_1 = null;
}
// 挂多单止盈单-2
try {
Log("多 --> 挂止盈单-2,价格: ", _takeprofit_order_price_2, ", 数量: ", _takeprofit_order_amount_2); // 输出日志
exchange.SetDirection("closebuy"); // 设置止盈平多交易方向
_takeprofit_order_id_2 = exchange.Sell(_takeprofit_order_price_2, _takeprofit_order_amount_2); // 挂止盈单
}
catch (error) {
Log("多 --> 挂止盈单-2,失败: ", error.message, "错误详情: ", error);
_takeprofit_order_id_2 = null;
}
// 挂多单止盈单-3
try {
Log("多 --> 挂止盈单-3,价格: ", _takeprofit_order_price_3, ", 数量: ", _takeprofit_order_amount_3); // 输出日志
exchange.SetDirection("closebuy"); // 设置止盈平多交易方向
_takeprofit_order_id_3 = exchange.Sell(_takeprofit_order_price_3, _takeprofit_order_amount_3); // 挂止盈单
}
catch (error) {
Log("多 --> 挂止盈单-3,失败: ", error.message, "错误详情: ", error);
_takeprofit_order_id_3 = null;
}
// 挂多单止盈单-4
try {
Log("多 --> 挂止盈单-4,价格: ", _takeprofit_order_price_4, ", 数量: ", _takeprofit_order_amount_4); // 输出日志
exchange.SetDirection("closebuy"); // 设置止盈平多交易方向
_takeprofit_order_id_4 = exchange.Sell(_takeprofit_order_price_4, _takeprofit_order_amount_4); // 挂止盈单
}
catch (error) {
Log("多 --> 挂止盈单-4,失败: ", error.message, "错误详情: ", error);
_takeprofit_order_id_4 = null;
}
// 挂多单止盈单-5
try {
Log("多 --> 挂止盈单-5,价格: ", _takeprofit_order_price_5, ", 数量: ", _takeprofit_order_amount_5); // 输出日志
exchange.SetDirection("closebuy"); // 设置止盈平多交易方向
_takeprofit_order_id_5 = exchange.Sell(_takeprofit_order_price_5, _takeprofit_order_amount_5); // 挂止盈单
}
catch (error) {
Log("多 --> 挂止盈单-5,失败: ", error.message, "错误详情: ", error);
_takeprofit_order_id_5 = null;
}
}
else if (_TAKEPROFIT_ORDER_OPEN && _positions_type == "Short" || positions[0].Type === PD_SHORT) {
// 挂单止盈
_takeprofit_order_price_1 = _FixPricePrecision(positions[0].Price * (1 - _TAKEPROFIT_ORDER_PRICEPERCENT_1 / 100), _price_precision); // 止盈价格-1
_takeprofit_order_amount_1 = _FixAmountPrecision(positions[0].Amount * _TAKEPROFIT_ORDER_AMOUNTPERCENT_1 / 100, _amount_precision); // 止盈数量-1
_takeprofit_order_price_2 = _FixPricePrecision(positions[0].Price * (1 - _TAKEPROFIT_ORDER_PRICEPERCENT_2 / 100), _price_precision); // 止盈价格-2
_takeprofit_order_amount_2 = _FixAmountPrecision(positions[0].Amount * _TAKEPROFIT_ORDER_AMOUNTPERCENT_2 / 100, _amount_precision); // 止盈数量-2
_takeprofit_order_price_3 = _FixPricePrecision(positions[0].Price * (1 - _TAKEPROFIT_ORDER_PRICEPERCENT_3 / 100), _price_precision); // 止盈价格-3
_takeprofit_order_amount_3 = _FixAmountPrecision(positions[0].Amount * _TAKEPROFIT_ORDER_AMOUNTPERCENT_3 / 100, _amount_precision); // 止盈数量-3
_takeprofit_order_price_4 = _FixPricePrecision(positions[0].Price * (1 - _TAKEPROFIT_ORDER_PRICEPERCENT_4 / 100), _price_precision); // 止盈价格-4
_takeprofit_order_amount_4 = _FixAmountPrecision(positions[0].Amount * _TAKEPROFIT_ORDER_AMOUNTPERCENT_4 / 100, _amount_precision); // 止盈数量-4
_takeprofit_order_price_5 = _FixPricePrecision(positions[0].Price * (1 - _TAKEPROFIT_ORDER_PRICEPERCENT_5 / 100), _price_precision); // 止盈价格-5
_takeprofit_order_amount_5 = _FixAmountPrecision(positions[0].Amount * _TAKEPROFIT_ORDER_AMOUNTPERCENT_5 / 100, _amount_precision); // 止盈数量-5
_takeprofit_order_hastakeprofit_1 = false; // 标记止盈,防止信息重复发送
_takeprofit_order_hastakeprofit_2 = false; // 标记止盈,防止信息重复发送
_takeprofit_order_hastakeprofit_3 = false; // 标记止盈,防止信息重复发送
_takeprofit_order_hastakeprofit_4 = false; // 标记止盈,防止信息重复发送
_takeprofit_order_hastakeprofit_5 = false; // 标记止盈,防止信息重复发送
// 挂空单止盈单
try {// 挂空单止盈单-1
Log("空 --> 挂止盈单-1,价格: ", _takeprofit_order_price_1, ", 数量: ", _takeprofit_order_amount_1); //输出日志
exchange.SetDirection("closesell"); //设置止盈平多交易方向
_takeprofit_order_id_1 = exchange.Buy(_takeprofit_order_price_1, _takeprofit_order_amount_1); //挂止盈单
}
catch (error) {
Log("空 --> 挂止盈单-1,失败: ", error.message, ", 错误详情: ", error);
_takeprofit_order_id_1 = null;
}
try {// 挂空单止盈单-2
Log("空 --> 挂止盈单-2,价格: ", _takeprofit_order_price_2, ", 数量: ", _takeprofit_order_amount_2); //输出日志
exchange.SetDirection("closesell"); //设置止盈平多交易方向
_takeprofit_order_id_2 = exchange.Buy(_takeprofit_order_price_2, _takeprofit_order_amount_2); //挂止盈单
}
catch (error) {
Log("空 --> 挂止盈单-2,失败: ", error.message, ", 错误详情: ", error);
_takeprofit_order_id_2 = null;
}
try {// 挂空单止盈单-3
Log("空 --> 挂止盈单-3,价格: ", _takeprofit_order_price_3, ", 数量: ", _takeprofit_order_amount_3); //输出日志
exchange.SetDirection("closesell"); //设置止盈平多交易方向
_takeprofit_order_id_3 = exchange.Buy(_takeprofit_order_price_3, _takeprofit_order_amount_3); //挂止盈单
}
catch (error) {
Log("空 --> 挂止盈单-3,失败: ", error.message, ", 错误详情: ", error);
_takeprofit_order_id_3 = null;
}
try {// 挂空单止盈单-4
Log("空 --> 挂止盈单-4,价格: ", _takeprofit_order_price_4, ", 数量: ", _takeprofit_order_amount_4); //输出日志
exchange.SetDirection("closesell"); //设置止盈平多交易方向
_takeprofit_order_id_4 = exchange.Buy(_takeprofit_order_price_4, _takeprofit_order_amount_4); //挂止盈单
}
catch (error) {
Log("空 --> 挂止盈单-4,失败: ", error.message, ", 错误详情: ", error);
_takeprofit_order_id_4 = null;
}
try {// 挂空单止盈单-5
Log("空 --> 挂止盈单-5,价格: ", _takeprofit_order_price_5, ", 数量: ", _takeprofit_order_amount_5); //输出日志
exchange.SetDirection("closesell"); //设置止盈平多交易方向
_takeprofit_order_id_5 = exchange.Buy(_takeprofit_order_price_5, _takeprofit_order_amount_5); //挂止盈单
}
catch (error) {
Log("空 --> 挂止盈单-5,失败: ", error.message, ", 错误详情: ", error);
_takeprofit_order_id_5 = null;
}
}
}
//// 检测挂单止盈是否成交
function _TakeProfit(positions, account, ticker) {
var price = ticker.Last;
if (_TAKEPROFIT_ORDER_OPEN && _positions_type == "Long") {
if(price > _takeprofit_order_price_1 && _takeprofit_order_hastakeprofit_1 == false)
{
Log("多 --> 止盈单-1,成交,价格: ", _N(_takeprofit_order_price_1, 6) + ", 数量: " + _N(_takeprofit_order_amount_1, 4)); // 日志输出
_takeprofit_order_id_1 = null; // 清空止盈单ID
_takeprofit_order_hastakeprofit_1 = true; // 标记止盈,防止信息重复发送
_takeprofit_order_price_1 = 0; // 重置止盈价格
_CalculateProfit(positions, account, ticker); //统计收益
}
if(price > _takeprofit_order_price_2 && _takeprofit_order_hastakeprofit_2 == false)
{
Log("多 --> 止盈单-2,价格: ", _N(_takeprofit_order_price_2, 6) + ", 数量: " + _N(_takeprofit_order_amount_2, 4)); // 输出
_takeprofit_order_id_2 = null; // 清空止盈单ID
_takeprofit_order_hastakeprofit_2 = true; // 标记止盈,防止信息重复发送
_takeprofit_order_price_2 = 0; // 重置止盈价格
_CalculateProfit(positions, account, ticker); // 统计收益
}
if(price > _takeprofit_order_price_3 && _takeprofit_order_hastakeprofit_3 == false)
{
Log("多 --> 止盈单-3,成交,价格: ", _N(_takeprofit_order_price_3, 6) + ", 数量: " + _N(_takeprofit_order_amount_3, 4)); // 输出
_takeprofit_order_id_3 = null; // 清空止盈单ID
_takeprofit_order_hastakeprofit_3 = true; // 标记止盈,防止信息重复发送
_takeprofit_order_price_3 = 0; // 重置止盈价格
_CalculateProfit(positions, account, ticker); // 统计收益
}
if(price > _takeprofit_order_price_4 && _takeprofit_order_hastakeprofit_4 == false)
{
Log("多 --> 止盈单-4,成交,价格: ", _N(_takeprofit_order_price_4, 6) + ", 数量: " + _N(_takeprofit_order_amount_4, 4)); // 输出
_takeprofit_order_id_4 = null; // 清空止盈单ID
_takeprofit_order_hastakeprofit_4 = true; // 标记止盈,防止信息重复发送
_takeprofit_order_price_4 = 0; // 重置止盈价格
_CalculateProfit(positions, account, ticker); // 统计收益
}
if(price > _takeprofit_order_price_5 && _takeprofit_order_hastakeprofit_5 == false)
{
Log("多 --> 止盈单-5,成交,价格: ", _N(_takeprofit_order_price_5, 6) + ", 数量: " + _N(_takeprofit_order_amount_5, 4)); // 输出
_takeprofit_order_id_5 = null; // 清空止盈单ID
_takeprofit_order_hastakeprofit_5 = true; // 标记止盈,防止信息重复发送
_takeprofit_order_price_5 = 0; // 重置止盈价格
_CalculateProfit(positions, account, ticker); // 统计收益
}
}
////空单止盈
else if (_TAKEPROFIT_ORDER_OPEN && _positions_type == "Short") {
if(price < _takeprofit_order_price_1 && _takeprofit_order_hastakeprofit_1 == false)
{
Log("空 --> 止盈单-1,成交,价格: ", _N(_takeprofit_order_price_1, 6) + ", 数量: " + _N(_takeprofit_order_amount_1, 4));
_takeprofit_order_id_1 = null; // 清空止盈单ID
_takeprofit_order_hastakeprofit_1 = true; // 标记止盈,防止信息重复发送
_takeprofit_order_price_1 = 0; // 重置止盈价格
_CalculateProfit(positions, account, ticker); //统计收益
}
if(price < _takeprofit_order_price_2 && _takeprofit_order_hastakeprofit_2 == false)
{
Log("空 --> 止盈单-2,成交,价格: ", _N(_takeprofit_order_price_2, 6) + ", 数量: " + _N(_takeprofit_order_amount_2, 4));
_takeprofit_order_id_2 = null; // 清空止盈单ID
_takeprofit_order_hastakeprofit_2 = true; // 标记止盈,防止信息重复发送
_takeprofit_order_price_2 = 0; // 重置止盈价格
_CalculateProfit(positions, account, ticker); //统计收益
}
if(price < _takeprofit_order_price_3 && _takeprofit_order_hastakeprofit_3 == false)
{
Log("空 --> 止盈单-3,成交,价格: ", _N(_takeprofit_order_price_3, 6) + ", 数量: " + _N(_takeprofit_order_amount_3, 4));
_takeprofit_order_id_3 = null; // 清空止盈单ID
_takeprofit_order_hastakeprofit_3 = true; // 标记止盈,防止信息重复发送
_takeprofit_order_price_3 = 0; // 重置止盈价格
_CalculateProfit(positions, account, ticker); //统计收益
}
if(price < _takeprofit_order_price_4 && _takeprofit_order_hastakeprofit_4 == false)
{
Log("空 --> 止盈单-4,成交,价格: ", _N(_takeprofit_order_price_4, 6) + ", 数量: " + _N(_takeprofit_order_amount_4, 4));
_takeprofit_order_id_4 = null; // 清空止盈单ID
_takeprofit_order_hastakeprofit_4 = true; // 标记止盈,防止信息重复发送
_takeprofit_order_price_4 = 0; // 重置止盈价格
_CalculateProfit(positions, account, ticker); //统计收益
}
if(price < _takeprofit_order_price_5 && _takeprofit_order_hastakeprofit_5 == false)
{
Log("空 --> 止盈单-5,成交,价格: ", _N(_takeprofit_order_price_5, 6) + ", 数量: " + _N(_takeprofit_order_amount_5, 4));
_takeprofit_order_id_5 = null; // 清空止盈单ID
_takeprofit_order_hastakeprofit_5 = true; // 标记止盈,防止信息重复发送
_takeprofit_order_price_5 = 0; // 重置止盈价格
_CalculateProfit(positions, account, ticker); //统计收益
}
}
}
// 止损(市价止损)
function _StopLoss(positions, account, ticker)
{
var price = ticker.Last;
if (positions.length > 0 && positions[0].Type == PD_LONG) {
if (price < _stoploss_price) {
Log("多单止损, 全部平仓")
Log("止损价格: ", _N(_stoploss_price, 6), ", 持仓价格: ", _N(positions[0].Price));
_Cover_1(); // 快速平仓
_ResetVariables(); // 重置变量
_CalculateProfit(positions, account, ticker); //统计收益
}
}
else if (positions.length > 0 && positions[0].Type == PD_SHORT) {
if (price > _stoploss_price) {
Log("空单止损, 全部平仓")
Log("止损价格: ", _N(_stoploss_price, 6), ", 持仓价格: ", _N(positions[0].Price));
_Cover_1(); // 快速平仓
_ResetVariables(); // 重置变量
_CalculateProfit(positions, account, ticker); //统计收益
}
}
}
//// 回调止盈(固定回调)
function _PullbackTakeProfit_Fixed(positions, account, ticker)
{
var price = ticker.Last;
if (positions[0].Type == PD_LONG && _positions_type == "Long") { // 开仓之后两秒,才执行这个检测
if(price > _pullback_fixed_startprice && _pullback_fixed_switch == false )
{
Log("多 --> 固定回调止盈开启。当前价格:" + _N(positions[0].Price, 6)); // 开始回调止盈时发出一条消息
_PEAK_PRICE_IN_POSITIONS = price; // 开始时记录价格低点
_pullback_fixed_switch = true;
}
if(_pullback_fixed_switch)
{
// 已达到触发价格,监控是否止盈
_PEAK_PRICE_IN_POSITIONS = price > _PEAK_PRICE_IN_POSITIONS ? price : _PEAK_PRICE_IN_POSITIONS; // 更新价格高点
_pullbakc_fixed_price_1 = _PEAK_PRICE_IN_POSITIONS * (1 - _PULLBACK_FIXED_PRICEPERCENT_1 / 100); // 计算回调的止盈价格(使用的是交易对价格回撤百分比)
_pullbakc_fixed_price_2 = _PEAK_PRICE_IN_POSITIONS * (1 - _PULLBACK_FIXED_PRICEPERCENT_2 / 100); // 计算回调的止盈价格(使用的是交易对价格回撤百分比)
//_PULLBACK_PROFIT_PRICE_11 = take_profit_price_11; // 用于打印回调止盈价格
//_PULLBACK_PROFIT_PRICE_12 = take_profit_price_12; // 用于打印回调止盈价格
if (price < _pullbakc_fixed_price_1 && _pullback_fixed_hastakeprofit == false) {// 达到回调止盈点位1,则部分减仓
var amount = _FixAmountPrecision(_order_size * _PULLBACK_FIXED_AMOUNTPERCENT_1 / 100, _amount_precision); // 止盈数量(下单量的百分比)
Log("多 --> 固定回调平仓 1, 数量: " + amount);
Log(
"价格高点: ", _N(_PEAK_PRICE_IN_POSITIONS, 6),
", 回调价格: ", _N(_pullbakc_fixed_price_1, 6),
", 当前价格: ", _N(price, 6),
", 持仓价格: ", _N(positions[0].Price, 6)); // 输出回调止盈信息
_ReduceLong(-1, amount); // 多单减仓
_CalculateProfit(positions, account, ticker); //统计收益
_pullback_fixed_hastakeprofit = true; // 是否止盈过一次,防止回调之后连续减仓
}
if (price < _pullbakc_fixed_price_2) {// 达到回调止盈点位2,则完全平仓
Log("多 --> 固定回调平仓 2,当前持仓全部清空。");
Log(
"价格高点: ", _N(_PEAK_PRICE_IN_POSITIONS, 6),
", 回调价格: ", _N(_pullbakc_fixed_price_2, 6),
", 当前价格: ", _N(price, 6),
", 持仓价格: ", _N(positions[0].Price, 6)); // 输出回调止盈信息
_Cover_1(); // 快速平仓
_ResetVariables(); // 重置运算变量
_CalculateProfit(positions, account, ticker); // 统计收益
}
}
}
else if (positions[0].Type == PD_SHORT && _positions_type == "Short") {//开仓之后两秒才执行这个检测
if(price < _pullback_fixed_startprice && _pullback_fixed_switch == false)
{
Log("空 --> 固定回调止盈开启。当前价格:" + _N(positions[0].Price, 6)); // 开始回调止盈时发出一条消息
_PEAK_PRICE_IN_POSITIONS = price; // 开始时记录价格低点
_pullback_fixed_switch = true;
}
if(_pullback_fixed_switch)
{
// 空单已达到触发价格,监控是否止盈
_PEAK_PRICE_IN_POSITIONS = price < _PEAK_PRICE_IN_POSITIONS ? price : _PEAK_PRICE_IN_POSITIONS; // 更新价格低点
_pullbakc_fixed_price_1 = _PEAK_PRICE_IN_POSITIONS * (1 + _PULLBACK_FIXED_PRICEPERCENT_1 / 100); // 计算回调的止盈价格
_pullbakc_fixed_price_2 = _PEAK_PRICE_IN_POSITIONS * (1 + _PULLBACK_FIXED_PRICEPERCENT_2 / 100); // 计算回调的止盈价格
//_PULLBACK_PROFIT_PRICE_11 = take_profit_price_11; // 用于打印回调止盈价格
//_PULLBACK_PROFIT_PRICE_12 = take_profit_price_12; // 用于打印回调止盈价格
if (price > _pullbakc_fixed_price_1 && _pullback_fixed_hastakeprofit == false) {// 达到回调止盈点位1,则部分减仓
var amount = _FixAmountPrecision(_order_size * _PULLBACK_FIXED_AMOUNTPERCENT_1 / 100, _amount_precision); // 止盈数量(下单量的百分比)
Log("空 --> 固定回调平仓 1, 数量: " + amount);
Log(
"价格低点: ", _N(_PEAK_PRICE_IN_POSITIONS, 6),
", 回调价格: ", _N(_pullbakc_fixed_price_1, 6),
", 当前价格: ", _N(price, 6),
", 持仓价格: ", _N(positions[0].Price, 6)); // 输出回调止盈信息
_ReduceShort(-1,amount); // 空单减仓
_CalculateProfit(positions, account, ticker); // 统计收益
_pullback_fixed_hastakeprofit = true; // 是否止盈过一次,防止回调之后连续减仓
}
if (price > _pullbakc_fixed_price_2) {// 达到回调止盈点位2,则完全平仓
Log("空 --> 固定回调平仓 2,当前持仓全部清空。");
Log(
"价格低点: ", _N(_PEAK_PRICE_IN_POSITIONS, 6),
", 回调价格: ", _N(_pullbakc_fixed_price_2, 6),
", 当前价格: ", _N(price, 6),
", 持仓价格: ", _N(positions[0].Price, 6)); // 输出回调止盈信息
_Cover_1(); // 快速平仓
_ResetVariables(); // 重置运算变量
_CalculateProfit(positions, account, ticker); // 统计收益
}
}
}
}
//// 回调止盈(利润回调)
function _PullbackTakeProfit_Profit(positions, account, ticker)
{
var price = ticker.Last;
var positions_profit_percent = 100 * (positions[0].Type == PD_LONG ? ((price - positions[0].Price) / positions[0].Price) * _margin_level : ((positions[0].Price - price) / positions[0].Price) * _margin_level);
if (positions[0].Type == PD_LONG && _positions_type == "Long") {// 开仓之后两秒才执行这个检测
// 如果当前价格 > 利润回调止盈价格,且回调止盈开关未开启,且止盈次数 < 最大止盈次数,且当前利润 > 利润峰值
if( price > _pullback_profit_startprice
&& _pullback_profit_switch == false
&& _pullback_profit_repeattimes < _PULLBACK_PROFIT_MAXREPEATTIMES
&& positions_profit_percent > _PEAK_PROFIT_IN_POSITIONS )
{
Log("多 --> 利润回调止盈第 " + (_pullback_profit_repeattimes + 1) + " 次开启。当前利润:" + _N(positions_profit_percent, 2) + "%"); // 开始回调止盈时发出一条消息
_PEAK_PROFIT_IN_POSITIONS = positions_profit_percent; // 开始时记录盈利点
_pullback_profit_switch = true; // 打开利润回调止盈开关
_pullback_profit_switch_2 = true; // 打开利润回调平仓开关
_pullback_profit_hastakeprofit = false; // 利润回调再次进行
}
// 如果利润回调开关已打开,且回调止盈次数 < 最大止盈次数
if(_pullback_profit_switch && _pullback_profit_repeattimes <= _PULLBACK_PROFIT_MAXREPEATTIMES) // 回调止盈已开启,且当前止盈次数 小于 最多止盈次数
{
// 多单已达到触发价格,监控是否止盈
_PEAK_PROFIT_IN_POSITIONS = positions_profit_percent > _PEAK_PROFIT_IN_POSITIONS ? positions_profit_percent : _PEAK_PROFIT_IN_POSITIONS; // 更新仓位利润高点
_pullback_profit_price = _PEAK_PROFIT_IN_POSITIONS * (100 - _PULLBACK_PROFIT_MULT_1 * Math.pow(1/_PEAK_PROFIT_IN_POSITIONS * 2000000,1/3)) / 100; // 计算回调止盈价格(利润百分比)
_pullback_profit_price_2 = _PEAK_PROFIT_IN_POSITIONS * (100 - _PULLBACK_PROFIT_MULT_2 * Math.pow(1/_PEAK_PROFIT_IN_POSITIONS * 2000000,1/3)) / 100; // 计算回调清仓价格(利润百分比)
//_pullback_profit_price = _PEAK_PROFIT_IN_POSITIONS * (1 - _PULLBACK_PROFIT_PRICEPERCENT / 100); // 计算仓位利润的回调点
if (positions_profit_percent < _pullback_profit_price && _pullback_profit_hastakeprofit == false) {// 达到回调止盈点位1,则部分减仓
var amount = _FixAmountPrecision(_order_size * _PULLBACK_PROFIT_AMOUNTPERCEHT / 100, _amount_precision); // 止盈数量(下单量的百分比)
Log("多 --> 利润回调第" + (_pullback_profit_repeattimes + 1) + "次减仓,数量: " + amount);
Log(
"最高利润: ", _N(_PEAK_PROFIT_IN_POSITIONS , 2) + "%",
", 当前利润: ", _N(positions_profit_percent, 2) + "%",
", 当前价格: ", _N(price, 6),
", 持仓价格: ", _N(positions[0].Price, 6)); // 输出回调止盈信息
_ReduceLong(-1, amount); // 多单减仓
_CalculateProfit(positions, account, ticker); //统计收益
//_PEAK_PROFIT_IN_POSITIONS = _PEAK_PROFIT_IN_POSITIONS * (1 - Math.sqrt(_PULLBACK_PROFIT_PRICEPERCENT) / 100) //峰值下降一点
_PEAK_PROFIT_IN_POSITIONS = _PEAK_PROFIT_IN_POSITIONS * 0.97; // 止盈之后,利润峰值下降一点
_pullback_profit_hastakeprofit = true; // 已经止盈过了
_pullback_profit_repeattimes += 1; // 执行了一次止盈回调,次数+1
_pullback_profit_switch = false; // 利润回调之后要关一下开关
_pullback_profit_price = 0; // 重置利润回调止盈
if(_pullback_profit_repeattimes >= _PULLBACK_PROFIT_MAXREPEATTIMES)
{
Log("利润回调止盈次数已用尽。"); //次数用尽消息
}
}
}
// 回调清仓
// 启用了回调止盈平仓,并且临时开关打开了,并且当前利润 < 平仓利润
if (_PULLBACK_PROFIT_OPEN_2 && _pullback_profit_switch_2 && positions_profit_percent < _pullback_profit_price_2) {// 达到回调止盈点位2,则完全平仓
Log("多 --> 利润回调平仓,当前持仓全部清空。");
Log(
"最高利润: ", _N(_PEAK_PROFIT_IN_POSITIONS , 2) + "%",
", 当前利润: ", _N(positions_profit_percent, 2) + "%",
", 当前价格: ", _N(price, 6),
", 持仓价格: ", _N(positions[0].Price, 6)); // 输出回调止盈信息
_Cover_1(); // 快速平仓
_ResetVariables(); // 重置运算变量
_CalculateProfit(positions, account, ticker); // 统计收益
}
}
else if (positions[0].Type == PD_SHORT && _positions_type == "Short") {// 开仓之后两秒才执行这个检测
// 如果当前价格 < 利润回调止盈价格,且回调止盈开关未开启,且止盈次数 < 最大止盈次数,且当前利润 > 利润峰值
if( price < _pullback_profit_startprice
&& _pullback_profit_switch == false
&& _pullback_profit_repeattimes < _PULLBACK_PROFIT_MAXREPEATTIMES
&& positions_profit_percent > _PEAK_PROFIT_IN_POSITIONS )
{
Log("空 --> 利润回调止盈第 " + (_pullback_profit_repeattimes + 1) + " 次开启。当前利润:" + _N(positions_profit_percent, 2) + "%"); // 开始回调止盈时发出一条消息
_PEAK_PROFIT_IN_POSITIONS = positions_profit_percent; // 记录开始时盈利百分比
_pullback_profit_switch = true; // 打开利润回调止盈开关
_pullback_profit_switch_2 = true; // 打开利润回调平仓开关
_pullback_profit_hastakeprofit = false; // 利润回调再次进行
}
if(_pullback_profit_switch && _pullback_profit_repeattimes < _PULLBACK_PROFIT_MAXREPEATTIMES) // 回调止盈已开启,且当前止盈次数 小于 最多止盈次数
{
// 空单已达到触发价格,监控是否止盈
_PEAK_PROFIT_IN_POSITIONS = positions_profit_percent > _PEAK_PROFIT_IN_POSITIONS ? positions_profit_percent : _PEAK_PROFIT_IN_POSITIONS; // 更新盈利高点
_pullback_profit_price = _PEAK_PROFIT_IN_POSITIONS * (100 - _PULLBACK_PROFIT_MULT_1 * Math.pow(1/_PEAK_PROFIT_IN_POSITIONS * 2000000,1/3)) /100; // 计算回调止盈价格(利润百分比)
_pullback_profit_price_2 = _PEAK_PROFIT_IN_POSITIONS * (100 - _PULLBACK_PROFIT_MULT_2 * Math.pow(1/_PEAK_PROFIT_IN_POSITIONS * 2000000,1/3)) / 100; // 计算回调清仓价格(利润百分比)
//_pullback_profit_price = _PEAK_PROFIT_IN_POSITIONS * (1 - _PULLBACK_PROFIT_PRICEPERCENT / 100); // 计算回调的止盈价格(使用的是交易对价格回撤百分比)
if (positions_profit_percent < _pullback_profit_price && _pullback_profit_hastakeprofit == false) { // 达到回调止盈点位1,则部分减仓
var amount = _FixAmountPrecision(_order_size * _PULLBACK_PROFIT_AMOUNTPERCEHT / 100, _amount_precision); // 止盈数量(下单量的百分比)
Log("空 --> 利润回调第" + (_pullback_profit_repeattimes + 1) + "次减仓,数量: " + amount);
Log(
"最高利润: ", _N(_PEAK_PROFIT_IN_POSITIONS , 2) + "%",
", 当前利润: ", _N(positions_profit_percent, 2) + "%",
", 当前价格: ", _N(price, 6),
", 持仓价格: ", _N(positions[0].Price, 6)); // 输出回调止盈信息
_ReduceShort(-1,amount); // 空单减仓
_CalculateProfit(positions, account, ticker); // 统计收益
//_PEAK_PROFIT_IN_POSITIONS = _PEAK_PROFIT_IN_POSITIONS * (1 - Math.sqrt(_PULLBACK_PROFIT_PRICEPERCENT) / 100) //峰值下降一点
_PEAK_PROFIT_IN_POSITIONS = _PEAK_PROFIT_IN_POSITIONS * 0.97; // 止盈之后,利润峰值下降一点
_pullback_profit_hastakeprofit = true; // 已经止盈过了
_pullback_profit_repeattimes += 1; // 执行了一次止盈回调,次数+1
_pullback_profit_switch = false; // 利润回调之后要关一下开关
_pullback_profit_price = 0; // 重置利润回调止盈
if(_pullback_profit_repeattimes >= _PULLBACK_PROFIT_MAXREPEATTIMES)
{
Log("利润回调止盈次数已用尽。"); //次数用尽消息
}
}
}
// 回调清仓
// 启用了回调止盈平仓,并且临时开关打开了,并且当前利润 < 平仓利润
if (_PULLBACK_PROFIT_OPEN_2 &&_pullback_profit_switch_2 && positions_profit_percent < _pullback_profit_price_2) {// 达到回调止盈点位2,则完全平仓
Log("空 --> 利润回调平仓,当前持仓全部清空。");
Log(
"最高利润: ", _N(_PEAK_PROFIT_IN_POSITIONS , 2) + "%",
", 当前利润: ", _N(positions_profit_percent, 2) + "%",
", 当前价格: ", _N(price, 6),
", 持仓价格: ", _N(positions[0].Price, 6)); // 输出回调止盈信息
_Cover_1(); // 快速平仓
_ResetVariables(); // 重置运算变量
_CalculateProfit(positions, account, ticker); // 统计收益
}
}
}
// 收益统计
function _CalculateProfit(positions, account, ticker)
{
// 重新获取一下账户持仓与资产
var account_asset = _GetAccountAsset(positions, account, ticker)
// 当前总收益 = 上一次总收益 + 本次的收益
var current_profit = (account_asset - _init_asset) - _profit_local; //本次收益
_profit_local += current_profit; //总收益
//// 检查重启后是否存在多单或空单
if (current_profit > 0)
{
_take_profit_count++;
}
_trade_count++;
LogProfit(_N(_profit_local, 4), "本次收益: ", _N(current_profit, 6),", 当前资金: ", _N(account_asset, 4));
_SaveUserDatasLocal();
}
function main()
{
_trade_currency = _C(exchange.GetCurrency); // 获取交易对信息
Log("交易对: ",_trade_currency);
_SetContract(_trade_currency); // 设置合约
positions = _C(exchange.GetPositions); // 获取仓位信息
account = _C(exchange.GetAccount); // 获取账户信息
ticker = _C(exchange.GetTicker); // 获取市场行情
_InitDatas(positions, account, ticker); // 初始化数据
_Initialize(positions); // 重启后检查是否存在多单和空单
while (true)
{
////////////////////////////消息监测//////////////////////////////////////////////////////////////////////////
var command = GetCommand(); // 监测消息
if (command)
{ // 如果有消息,则执行命令
Log("接收到的命令: ", command, "#FF1CAE");
if(command.indexOf("FMZ_") == 0)
{
_RunCommand(command); //执行FMZ交互指令
}
else
{
try{
var TV_message = JSON.parse(command); //格式化消息,方便之后的处理
{
_RunTVCommand(TV_message); //执行TradingView指令
}
}
catch(error)
{
Log("JSON解析出现错误 : ", error);
}
}
}
////////////////////////////消息监测//////////////////////////////////////////////////////////////////////////
///////////////////////////仓位监控///////////////////////////////////////////////////////////////////////////
_PositionMonitoring(); // 仓位监控
//////////////////////////////////////////////////////////////////////////////////////////////////////
Sleep(_interval); // 程序运行间隔
}
}