Back to Strategies
RSI Mean-Reversion Bounce
Code Strategy by 0xsDp5JzBDn·2026-07-02
// Env: RSI_PERIOD, RSI_OVERSOLD, RSI_OVERBOUGHT, TREND_EMA, INTERVAL, TP_PERCENT, SL_PERCENT
async function getCloses(interval, limit) {
const res = await $.Http.get("https://fapi.binance.com/fapi/v1/klines", {
symbol: $.Price.symbol,
interval,
limit
});
if (res.status !== 200) return null;
const raw = JSON.parse(res.text);
return raw.map(c => parseFloat(c[4]));
}
const RSI_PERIOD = Number($.Env.RSI_PERIOD || 14);
const RSI_OVERSOLD = Number($.Env.RSI_OVERSOLD || 30);
const RSI_OVERBOUGHT = Number($.Env.RSI_OVERBOUGHT || 70);
const TREND_EMA = Number($.Env.TREND_EMA || 50);
const INTERVAL = $.Env.INTERVAL || "5m";
const TP_PERCENT = Number($.Env.TP_PERCENT || 1.0);
const SL_PERCENT = Number($.Env.SL_PERCENT || 0.8);
let S = (await $.Storage.get()) || { position: null, entryPrice: null };
let nextAction = null;
if (S.position) {
const roi = $.Strategy.roi(true, S.entryPrice, $.Price.price);
if (roi !== null) {
const profit = S.position === "LONG" ? roi : -roi;
if (profit >= TP_PERCENT || profit <= -SL_PERCENT) {
nextAction = { type: $.Action.EXIT };
}
}
}
if (!nextAction && !S.position) {
const closes = await getCloses(INTERVAL, Math.max(TREND_EMA * 2, 100));
if (closes && closes.length > TREND_EMA) {
const rsi = new $.Ta.RSI(RSI_PERIOD);
const trend = new $.Ta.EMA(TREND_EMA);
for (const c of closes) {
rsi.update(c);
trend.update(c);
}
if (rsi.isStable && trend.isStable) {
const rsiVal = rsi.getResult();
const trendVal = trend.getResult();
const price = $.Price.price;
if (rsiVal <= RSI_OVERSOLD && price > trendVal) {
nextAction = { type: $.Action.LONG, side: "LONG" };
} else if (rsiVal >= RSI_OVERBOUGHT && price < trendVal) {
nextAction = { type: $.Action.SHORT, side: "SHORT" };
}
}
}
}
if (nextAction) {
await $.Strategy.action(nextAction.type);
if (nextAction.type === $.Action.EXIT) {
S.position = null;
S.entryPrice = null;
} else {
S.position = nextAction.side;
S.entryPrice = $.Price.price;
}
}
await $.Storage.set(S);