AI BOT BACKTEST — 2018-04-14 ~ 2026-08-31 (8.4년)

같은 AI가 짜준 자동매매 봇 5개,
5억 7,653만원과 1만 2천원으로 갈렸습니다

코딩을 모르는 초보자가 AI에게 "유명한 자동매매 전략 5개를 짜 달라"고 하면 받게 되는 그 전략들(RSI 반등·골든크로스·MACD·볼린저밴드·변동성 돌파)을, AI가 준 기본값 그대로 업비트 비트코인 4시간봉 8.4년에 넣고 실측했습니다. 비용은 편도 0.1%, 신호는 봉 종가 확정 후 다음 봉 반영입니다. 아래 코드로 전부 재현됩니다.

재현 코드 받기 이 실측의 한계 →

1. 비트코인 — 5개 중 1개만 보유를 이겼습니다

v1 = AI가 준 그대로 · v2 = AI의 개선안(종가 > 200일 이동평균선일 때만 매매) 적용

전략 (1000만원 시작)최종 잔고연복리최대낙폭검증 연복리
(2024~)
검증 낙폭매매 수
그냥 보유1억 3,048만원35.9%-74.8%27.2%-50.3%1
v1 골든크로스5억 7,653만원62.2%-53.4%44.8%-25.0%550
v2 골든크로스+필터3억 414만원50.3%-30.9%32.6%-24.4%306
v1 MACD5,023만원21.2%-56.9%15.3%-37.8%671
v2 MACD+필터7,276만원26.7%-33.1%18.0%-24.3%374
v1 RSI 반등55만원-29.2%-95.4%-15.9%-50.1%194
v1 볼린저 역추세50만원-30.0%-95.3%-19.7%-48.4%185
v1 변동성 돌파12,000원-55.0%-99.9%-55.2%-89.3%2,966
그냥 보유가 1억 3,048만원(35.9%)인 시장에서 골든크로스(5·20)는 5억 7,653만원 — 보유의 4.4배입니다. 반대로 변동성 돌파는 매매 2,966번의 비용이 계좌를 지웠고, 비용을 0으로 놓아도 연복리 -8.6%로 신호 자체가 손실이었습니다.

2. 이더리움 — 같은 부호

전략 (1000만원 시작)최종 잔고연복리최대낙폭검증 연복리
(2024~)
검증 낙폭매매 수
그냥 보유6,189만원24.3%-89.8%3.7%-65.2%1
v1 골든크로스15억 8,101만원83.0%-54.6%39.7%-52.3%538
v2 골든크로스+필터3억 5,048만원52.9%-40.4%35.0%-23.6%305
v1 MACD2억 300만원43.2%-64.8%29.0%-46.7%661
v2 MACD+필터2억 6,466만원47.8%-37.4%27.6%-23.7%355
v1 RSI 반등31만원-33.9%-97.8%-24.7%-63.5%209
v1 볼린저 역추세41만원-31.7%-97.1%-23.4%-63.8%204
v1 변동성 돌파22,000원-51.8%-99.8%-49.0%-84.4%2,932

3. 요행인지 스스로 반박해 봤습니다

대본을 쓰기 전에 결론을 공격하는 것이 이 채널의 규칙입니다.

① 이웃 격자 — 골든크로스 설정 주변 24칸(fast 3~8 × slow 15~30)을 전부 돌려도 연복리 최소 38.5% ~ 최대 72.5%. 기본값이 외딴 요행 봉우리가 아닙니다.
② 연도별 — 2022년 하락장: 보유 -62.9% vs v1 -29.3% vs 필터 단 v2 -1.0%. 2026년(집계일까지): 보유 -15.5% vs v1 22.7%. 강세장 한 구간에 몰빵된 성적이 아닙니다.
③ 교차시장 — 같은 규칙을 바이낸스 달러 마켓에 옮기면 v1 연복리가 24.9%로 떨어집니다(업비트 62.2%). 수익이 급등 구간 몇 번에 몰려 있어 가격 경로가 다르면 결과가 크게 갈립니다. 이 성적은 업비트 원화 기준이며, 다른 시장에 그대로 들고 가면 안 됩니다.

이 실측의 한계 — 접지 말고 읽어 주세요

· 전부 과거 데이터 백테스트입니다. 미래 수익을 보장하지 않습니다.
· 비용은 편도 0.1% 가정이며 슬리피지·세금·호가 공백은 반영하지 않았습니다.
· v1 골든크로스의 최대낙폭은 -53.4% — 계좌가 반토막 나는 구간을 견뎌야 나오는 수익입니다. 필터를 단 v2도 -30.9%까지 빠졌습니다.
· 결과는 자산·시장·기간에 따라 달라집니다. 검증(2024~) 구간 성적을 항상 함께 보세요.

재현 코드 — 믿지 말고 직접 돌려보세요

업비트 공개 API로 데이터를 받아 위 표를 그대로 다시 계산합니다. 기준일이 2026.8.31로 고정되어 있어 영상·페이지와 같은 숫자가 나옵니다.

ai_bot_backtest.py
다운로드
# -*- coding: utf-8 -*-
"""AI가 짜 준 자동매매 봇 5개 — 업비트 4시간봉 백테스트 재현 코드
영상: 「같은 AI가 짜준 자동매매 봇인데 5.8억과 1.2만원」 (AlgoLab, 2026-09)

필요한 것: Python 3.10+ · requests · numpy   (pip install requests numpy)
실행:      python ai_bot_backtest.py
           업비트 공개 API에서 4시간봉을 내려받아(약 2분) 표를 출력합니다.

ASOF: 데이터를 2026-08-31 까지로 자릅니다 — 영상과 같은 숫자가 나오게 하기 위한
      기준일입니다. 최신까지 보려면 ASOF = None 으로 바꾸세요(숫자는 영상과 달라집니다).
      업비트 캔들 페이지 경계 때문에 '그냥 보유' 등 일부 값이 1% 미만으로 다를 수 있습니다.

규칙(영상과 동일):
 · 전략 5개는 AI(클로드)가 초보자 프롬프트에 준 것 그대로, 기본 파라미터 그대로.
 · 신호는 봉 종가에서 확정 → 다음 봉부터 반영(미래참조 방지). 숏 없음, 현금 무수익.
 · 비용: 포지션이 바뀔 때마다 변화분 × 편도 0.1%.
 · v2 = 같은 신호 × 추세 필터(종가 > 1200봉 이동평균 ≈ 200일선) — AI가 준 개선안.
한계: 과거 데이터 백테스트라 미래를 보장하지 않습니다. 슬리피지·세금 미반영.
"""
import datetime
import time

import numpy as np
import requests

ASOF = datetime.date(2026, 8, 31)          # 영상 기준일. None 이면 오늘까지
COST = 0.001                               # 편도 0.1%
FILTER_N = 1200                            # 4시간봉 1200개 = 200일
START = 1000                               # 만원


# ── 업비트 4시간봉 내려받기 (공개 API, 키 불필요) ───────────────────────────
def fetch_upbit_4h(market):
    url = "https://api.upbit.com/v1/candles/minutes/240"
    to = None
    rows = []
    while True:
        params = {"market": market, "count": 200}
        if to:
            params["to"] = to
        r = requests.get(url, params=params, timeout=10)
        r.raise_for_status()
        batch = r.json()
        if not batch:
            break
        rows += batch
        to = batch[-1]["candle_date_time_utc"] + "Z"
        time.sleep(0.11)                    # 공개 API 예의
        if len(batch) < 200:
            break
    rows.sort(key=lambda x: x["candle_date_time_kst"])
    o = np.array([x["opening_price"] for x in rows], float)
    h = np.array([x["high_price"] for x in rows], float)
    l = np.array([x["low_price"] for x in rows], float)
    c = np.array([x["trade_price"] for x in rows], float)
    d = [x["candle_date_time_kst"][:10] for x in rows]
    if ASOF:                                # 캐시 유무와 무관하게 항상 같은 기준으로 자른다
        keep = [i for i, x in enumerate(d) if x <= ASOF.isoformat()]
        o, h, l, c = o[keep], h[keep], l[keep], c[keep]
        d = [d[i] for i in keep]
    return d, o, h, l, c


# ── 지표 ────────────────────────────────────────────────────────────────────
def sma(x, n):
    out = np.full(len(x), np.nan)
    if len(x) >= n:
        cs = np.cumsum(np.insert(x, 0, 0.0))
        out[n - 1:] = (cs[n:] - cs[:-n]) / n
    return out


def ema(x, n):
    a = 2.0 / (n + 1)
    out = np.empty(len(x))
    out[0] = x[0]
    for i in range(1, len(x)):
        out[i] = a * x[i] + (1 - a) * out[i - 1]
    return out


def rstd(x, n):
    out = np.full(len(x), np.nan)
    if len(x) >= n:
        from numpy.lib.stride_tricks import sliding_window_view as swv
        out[n - 1:] = swv(x, n).std(axis=1)
    return out


def ffill_signal(buy, sell, warm, n):
    s = np.full(n, np.nan)
    s[sell] = 0.0
    s[buy] = 1.0
    s[:warm] = 0.0
    idx = np.arange(n)
    has = ~np.isnan(s)
    last = np.maximum.accumulate(np.where(has, idx, 0))
    out = s[last]
    out[np.isnan(out)] = 0.0
    return out


# ── AI가 준 전략 5개 (기본값 그대로) ────────────────────────────────────────
def ai_rsi(o, h, l, c, n=14, lo=30, hi=70):
    d = np.diff(c, prepend=c[0])
    up = np.where(d > 0, d, 0.0)
    dn = np.where(d < 0, -d, 0.0)
    au, ad = ema(up, n), ema(dn, n)
    rsi = 100 - 100 / (1 + au / np.where(ad == 0, 1e-9, ad))
    return ffill_signal(rsi < lo, rsi > hi, n + 1, len(c))


def ai_goldencross(o, h, l, c, fast=5, slow=20):
    f, s = sma(c, fast), sma(c, slow)
    out = np.zeros(len(c))
    m = ~(np.isnan(f) | np.isnan(s))
    out[m] = (f[m] > s[m]).astype(float)
    return out


def ai_macd(o, h, l, c, fast=12, slow=26, sig=9):
    m = ema(c, fast) - ema(c, slow)
    return (m > ema(m, sig)).astype(float)


def ai_bollinger(o, h, l, c, n=20, k=2.0):
    ma, sd = sma(c, n), rstd(c, n)
    buy = (c < ma - k * sd) & ~np.isnan(sd)
    sell = (c > ma + k * sd) & ~np.isnan(sd)
    return ffill_signal(buy, sell, n + 1, len(c))


def ai_volbreak(o, h, l, c, k=0.5):
    rng = np.r_[np.nan, h[:-1] - l[:-1]]
    s = np.zeros(len(c))
    m = ~np.isnan(rng)
    s[m] = (c[m] > o[m] + k * rng[m]).astype(float)
    return s


STRATS = {"RSI 반등": ai_rsi, "골든크로스": ai_goldencross, "MACD": ai_macd,
          "볼린저 역추세": ai_bollinger, "변동성 돌파": ai_volbreak}


# ── 평가 ────────────────────────────────────────────────────────────────────
def evaluate(sig, ret, d, ppy, warm):
    pos = np.r_[0.0, sig[:-1]]
    g = (1 + pos * ret) * (1 - COST * np.abs(np.diff(np.r_[0.0, pos])))
    gg = g[warm:]
    eq = np.cumprod(gg)
    yrs = len(gg) / ppy
    cagr = eq[-1] ** (1 / yrs) - 1 if eq[-1] > 0 else -1.0
    mdd = float((eq / np.maximum.accumulate(eq) - 1).min())
    return eq[-1], cagr, mdd


def main():
    for market, label in [("KRW-BTC", "비트코인"), ("KRW-ETH", "이더리움")]:
        print(f"\n{label} ({market}) 4시간봉 내려받는 중...")
        d, o, h, l, c = fetch_upbit_4h(market)
        n = len(c)
        ret = np.zeros(n)
        ret[1:] = c[1:] / c[:-1] - 1
        yrs_all = (datetime.date.fromisoformat(d[-1]) -
                   datetime.date.fromisoformat(d[0])).days / 365.25
        ppy = n / yrs_all
        warm = FILTER_N + 1
        filt = np.zeros(n)
        ma = sma(c, FILTER_N)
        m = ~np.isnan(ma)
        filt[m] = (c[m] > ma[m]).astype(float)

        print(f"  {n:,}봉 · {d[warm]} ~ {d[-1]}")
        print(f"  {'전략':<14}{'최종(만원)':>12}{'연복리':>9}{'최대낙폭':>9}")
        mult, cagr, mdd = evaluate(np.ones(n), ret, d, ppy, warm)
        print(f"  {'그냥 보유':<14}{START*mult:>12,.0f}{cagr:>9.1%}{mdd:>9.1%}")
        for name, fn in STRATS.items():
            sig = fn(o, h, l, c)
            for tag, s in [("v1 " + name, sig), ("v2 " + name + "+필터", sig * filt)]:
                mult, cagr, mdd = evaluate(s, ret, d, ppy, warm)
                print(f"  {tag:<14}{START*mult:>12,.1f}{cagr:>9.1%}{mdd:>9.1%}")


if __name__ == "__main__":
    main()

직접 하기 어려우시면

AI는 봇을 잘 짜 줍니다. 문제는 어느 봇에 돈을 맡겨도 되는지는 짜 주지 않는다는 것입니다. 알고랩은 이런 검증을 포함해 전략 구현부터 자동매매 운영까지 대신해 드립니다.

알고랩에 맡기기 알고랩 소개 →
Strategy Lab · 이 검증 더 보기
이 검증을 영상으로 보기4분 43초 전략 후보 1,887개 전수 백테스트제대로 찾는 법 인기 지표 13종 888조합 검증 — 살아남은 4개지표 검증 전략 검증 전체 보기 →

본 페이지의 모든 수치는 과거 데이터 기반 시뮬레이션이며 투자 권유가 아닙니다. 특정 종목·전략의 미래 수익을 보장하지 않습니다. 투자 판단과 책임은 투자자 본인에게 있습니다.