Name
趋势策略V10-公开
Author
夏天不打你
Strategy Description
Strategy Arguments
Argument | Default | Description |
---|---|---|
TradeCurrency | ETH_USD | (?基本设置)交易对(币本位用USD结尾,U本位用USDT结尾) |
Interval | 5000 | 程序运行周期(ms) |
UseQuarter | false | 季度合约,默认USDT永续合约 |
OnlyTrendJudgment | false | 只做趋势判断,不下单 |
EnableMessageSend | false | 推送消息 |
RunInKLinePeriod | true | (?趋势判断)按照K线周期执行策略核心 |
KLinePeriod | 60 | K线周期(min) |
EmaLength | 90 | EMA长度 |
EmaCoefficient | 0.004 | EMA有效系数 |
UseStddev | true | 使用标准差 |
UseRecordsMiddleValue | true | 使用K线中值来计算标准差,否则使用K线收盘价 |
StddevLength | 33 | 标准差长度 |
StddevDeviations | true | 标准差偏差 |
MarginLevel | 5 | (?下单设置)杠杆倍数 |
OrderSize | 10 | 下单数量/张数 |
OrderByMargin | true | 根据下单保证金来确定下单数量 |
OrderMarginPercent | 50 | 下单保证金百分比(根据初始资金计算)% |
PricePrecision | 2 | 下单价格精度(小数位) |
AmountPrecision | false | 下单数量精度(小数位) |
OneSizeInCurrentCoin | true | U本位合约中,一张所代表的币的数量 |
QuarterOneSizeValue | 10 | 币本位合约中,一张所代表的USDT数量 |
UseStopLoss | false | (?止盈止损)使用止损 |
StopLossPercent | 1.4 | 止损百分比% |
UseTakeProfit | false | 使用止盈 |
TakeProfitPercent | 10 | 止盈百分比% |
UseTrackingTakeProfit | false | 使用回调止盈 |
UsePositionRetracement | false | 使用持仓回撤百分比止盈,否则使用价格回撤百分比止盈 |
TakeProfitTriggerPercent | 5 | 回调止盈价格触发百分比% |
CallBakcPercent | true | 回调百分比% |
Button | Default | Description |
---|---|---|
SaveLocalData | false | 保存数据到本地 |
ClearLocalData | false | 清除本地数据 |
ClearLog | true | 清除日志 |
OrderSize | 10 | 下单张数 |
OrderMarginPercent | 25 | 下单保证金百分比% |
Source (javascript)
/*
趋势策略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);
}
}
Detail
https://www.fmz.com/strategy/320782
Last Modified
2021-12-15 15:31:53