Средний истинный диапазон (англ. Average True Range), или ATR, используется для измерения интенсивности волатильности рынка, показывает изменчивость рынка, но не отражает стабильность тренда и направления цен.
Средний реальный диапазон колебаний, полученный на основе расчета реальных колебаний за прошедшие N дней и реальных колебаний за день. Однодневный реальный диапазон колебаний основан на максимальном разрыве между тремя группами результатов: ((самая цена за день - самая низкая цена за день), ((самая цена за день - цена закрытия за день) и ((самая цена закрытия за день - самая низкая цена за день) с целью получения максимальной разницы в цене диапазона колебаний).
Индекс относительной силы (RSI) - это технический показатель, определяющий будущее движение рынка путем сравнения силы покупателей и продавцов в течение определенного периода времени.
RSI = 100 - (100/(1+RS)); RS = сумма числа закрытых и/или закрытых на n дней; Обычно RSI 50 считается средней линией, более 50 считается многоголовым рынком, меньше 50 - пустым рынком; Показатель RSI выше 70 рассматривается как состояние перекупления, после которого может произойти реванш или переход, а менее 30 - как состояние перепродажи, после которого может произойти рост.
ATR используется для фильтрации, когда ATR>ATRMa ((средний ATR за последние N дней) указывает на то, что рыночные колебания начали увеличиваться, и тенденция усиливается. RSI используется для генерации торговых сигналов.
/*backtest start: 2021-02-11 00:00:00 end: 2022-02-10 23:59:00 period: 15m basePeriod: 5m exchanges: [{"eid":"Huobi","currency":"BCH_USDT"}] args: [["rsi_period",12],["atrma_period",18]] */ /* * rsi_period: 强弱指标计算周期 * atr_period: 平均真实波幅计算周期 * atrma_period: 平均真实波幅均值计算呢周期 * tick_interval: 时间间隔 * slide_price: 下单滑动值 */ // RSI指示操作状态 var RSI_NONE = 0; var RSI_BUY = 1; var RSI_SELL = 2; var last_rsi_staus; // ATR活跃信号判断 function isAtrActive(records) { let atr = TA.ATR(records, atr_period); let atrma = atr[atr.length - 1]; if (atr.length > atrma_period) { let tmp_atr = 0; for (let i = atr.length - atrma_period; i < atr.length; i++) { tmp_atr += atr[i]; } atrma = tmp_atr / atr_period; } else { atrma = aval(atr.join("+")) / atr.length; } return atr[atr.length - 1] > atrma; } // 获取RSI操作状态 function getRsiStatus(records) { let rsi = TA.RSI(records, rsi_period)[records.length - 1]; if (rsi < 30) { return RSI_BUY; } else if (rsi > 70) { return RSI_SELL; } else { return RSI_NONE; } } // 取消未成交下单 function canelPendingOrders() { while (true) { let orders = _C(exchange.GetOrders); if (orders.length == 0) { break; } for (let i = 0; i < orders.length; i++) { exchange.CancelOrder(orders[i].Id); } } } function onTick() { let records = _C(exchange.GetRecords, PERIOD_M15); let ticker = _C(exchange.GetTicker); if (records == null || ticker == null || records.length < rsi_period || records.length < atr_period) { return; } if (isAtrActive(records)) { let rsi = getRsiStatus(records); if (rsi != RSI_NONE) { let account = _C(exchange.GetAccount); if (rsi == RSI_BUY && last_rsi_staus != RSI_BUY) { Log("买入信号"); last_rsi_staus = RSI_BUY; canelPendingOrders(); if(account.Balance>0){ let price = ticker.Last + slide_price; let amount = account.Balance / price * 0.99; exchange.Buy(price, amount); } } else if (rsi == RSI_SELL && last_rsi_staus != RSI_SELL) { Log("卖出信号"); last_rsi_staus = RSI_SELL; canelPendingOrders(); if (account.Stocks > 0) { let price = ticker.Last - slide_price; exchange.Sell(price, account.Stocks); } } } } last_records = records; } function main() { while (true) { onTick(); Sleep(tick_interval * 1000); } }
Аль-АльРецензия:RuntimeError: abort ((undefined) at Error at jsStackTrace, это круто
НожЕсть ли еще информация? Я посмотрю.