Стратегия ATR-RSI

Автор:Нож, Дата: 2022-02-13 17:17:17
Тэги:

Показатель Atr

Средний истинный диапазон (англ. Average True Range), или ATR, используется для измерения интенсивности волатильности рынка, показывает изменчивость рынка, но не отражает стабильность тренда и направления цен.

Методы расчета

Средний реальный диапазон колебаний, полученный на основе расчета реальных колебаний за прошедшие N дней и реальных колебаний за день. Однодневный реальный диапазон колебаний основан на максимальном разрыве между тремя группами результатов: ((самая цена за день - самая низкая цена за день), ((самая цена за день - цена закрытия за день) и ((самая цена закрытия за день - самая низкая цена за день) с целью получения максимальной разницы в цене диапазона колебаний).

Показатель Rsi

Индекс относительной силы (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, это круто

НожЕсть ли еще информация? Я посмотрю.