국내 대형주 · 삼성전자 · 급락 매수 · 실측 재현 페이지

대형주가 크게 빠진 날,
다음 날 바로 살까 반등을 보고 살까

2007년 말 시가총액 상위 40개 종목의 2005년 이후 실제 가격(야후 수정종가)에서, 종가가 직전 20거래일 최고 종가보다 20% 넘게 낮아진 첫 날을 모두 모았습니다. 같은 돈으로 두 가지를 견줍니다. ① 바로 — 다음 거래일 종가에 산다 ② 반등 보고 — 그 뒤 가장 낮았던 종가에서 10% 오른 날의 다음 거래일 종가에 산다 둘 다 바로 산 날부터 250거래일(약 1년) 뒤 같은 날 종가로 평가합니다.

371 / 538크게 빠진 538번 중 1년 뒤 바로 산 쪽이 더 남은 횟수 — 같은 날 평가라, 반등을 보고 산 값이 더 비쌌던 횟수와 같습니다
1,736만원삼성전자 2008년 10월 24일 — 다음 날 1,000만원어치 산 사람의 1년 뒤. 반등을 보고 산 사람은 1,600만원
224번바로 산 쪽도 1년 뒤 산 값보다 아래였던 횟수 — 바로 사면 오른다는 약속이 아닙니다

오늘 드리는 것 — 기준 한 줄

상황할 일
사려던 대형주가 20거래일 최고 종가보다 20% 넘게 빠졌다반등을 기다리지 말고 다음 날 산다
원래 살 생각이 없던 종목이 페이지의 질문이 아닙니다 — 빠졌다는 이유만으로 사라는 뜻이 아닙니다

삼성전자 — 빠진 날 다섯 번 전부

빠진 날바로 산 날바로 · 1년 뒤반등 보고 산 날반등 보고 · 1년 뒤평가일
2008-07-102008-07-111,070만원2008-07-251,055만원2009-07-03
2008-10-242008-10-271,736만원2008-10-291,600만원2009-10-20
2011-08-192011-08-221,837만원2011-09-021,650만원2012-08-22
2020-03-162020-03-171,807만원2020-03-251,757만원2021-03-23
2024-09-192024-09-201,404만원2024-11-191,562만원2025-10-01

1,000만원 기준 · 수정주가. 2024년 9월은 바로 산 뒤에도 두 달 가까이 더 빠져 반등을 기다린 쪽이 더 싸게 샀습니다.

다 모아 보면

한계 — 먼저 읽어 주세요

받아가기

돌리는 법: zip 을 풀고 python run_bigdrop.py

그대로 돌린 출력

대형주가 20일 최고 종가보다 20% 넘게 빠진 날 — 바로 살까, 반등(바닥 +10%)을 보고 살까 · 1년 뒤 같은 날 평가

== 국내 · 2007년 말 시가총액 상위 40종 (메인)
  빠진 날 538번 · 1년 뒤 바로 산 쪽이 더 남은 것 371번 · 반등을 보고 산 쪽 167번
  반등을 보고 산 값이 바로 산 값보다 비쌌던 것 371번(같은 날 평가라 위와 같은 수)
  반등을 기다린 기간 가운데 값 11거래일
  1,000만원 기준 1년 뒤 평균(기하): 바로 1,082만원 · 반등 보고 1,069만원
  1,000만원 기준 1년 뒤 평균(단순): 바로 1,206만원 · 반등 보고 1,196만원
  바로 산 쪽도 1년 뒤 산 값보다 아래였던 것 224번
  종목별 평균으로 바로가 앞선 종목 28/40 · 달로 묶으면 100/141달 · 해로 묶으면 17/21해
  반등을 본 쪽이 평균으로 앞선 해: 2014 · 2015 · 2018 · 2020
  2020년 빠진 날 49번 · 반등을 보고 산 쪽이 더 남은 것 31번
  20일선 위로 올라선 걸 보고 사기(평균 로그) +0.0525 — 바로 +0.0790 · 반등 보고 +0.0667
== 국내 · 대형주 36종 (개발 표본)
  빠진 날 469번 · 1년 뒤 바로 산 쪽이 더 남은 것 340번 · 반등을 보고 산 쪽 129번
  반등을 보고 산 값이 바로 산 값보다 비쌌던 것 340번(같은 날 평가라 위와 같은 수)
  반등을 기다린 기간 가운데 값 11거래일
  1,000만원 기준 1년 뒤 평균(기하): 바로 1,148만원 · 반등 보고 1,127만원
  1,000만원 기준 1년 뒤 평균(단순): 바로 1,280만원 · 반등 보고 1,262만원
  바로 산 쪽도 1년 뒤 산 값보다 아래였던 것 180번
  종목별 평균으로 바로가 앞선 종목 28/36 · 달로 묶으면 97/130달 · 해로 묶으면 18/21해
  반등을 본 쪽이 평균으로 앞선 해: 2014 · 2015 · 2020
  2020년 빠진 날 42번 · 반등을 보고 산 쪽이 더 남은 것 27번
  20일선 위로 올라선 걸 보고 사기(평균 로그) +0.1097 — 바로 +0.1382 · 반등 보고 +0.1195
== 미국 · 대형주 30종
  빠진 날 187번 · 1년 뒤 바로 산 쪽이 더 남은 것 117번 · 반등을 보고 산 쪽 70번
  반등을 보고 산 값이 바로 산 값보다 비쌌던 것 117번(같은 날 평가라 위와 같은 수)
  반등을 기다린 기간 가운데 값 10거래일
  1,000만원 기준 1년 뒤 평균(기하): 바로 1,104만원 · 반등 보고 1,117만원
  1,000만원 기준 1년 뒤 평균(단순): 바로 1,229만원 · 반등 보고 1,240만원
  바로 산 쪽도 1년 뒤 산 값보다 아래였던 것 37번
  종목별 평균으로 바로가 앞선 종목 13/30 · 달로 묶으면 44/65달 · 해로 묶으면 12/19해
  반등을 본 쪽이 평균으로 앞선 해: 2006 · 2007 · 2008 · 2016 · 2017 · 2018 · 2020
  2020년 빠진 날 34번 · 반등을 보고 산 쪽이 더 남은 것 24번
  20일선 위로 올라선 걸 보고 사기(평균 로그) +0.1002 — 바로 +0.0992 · 반등 보고 +0.1104

[기준선 — 빠진 날이 아니라 아무 달 첫 거래일에, 다음 날 산 것과 11거래일 늦게 산 것]
  국내 2007 상위 40: 9,872번 중 5,058번 늦게 산 값이 더 비쌌다
  국내 36: 8,955번 중 4,604번 늦게 산 값이 더 비쌌다
  국내 2007 상위 40 · 2008년 이후 빠진 날만: 461번 중 302번 바로가 더 남음
  국내 36 · 2008년 이후 빠진 날만: 402번 중 280번 바로가 더 남음

[삼성전자 005930 — 빠진 날 전부 · 1,000만원 기준 1년 뒤]
  2008-07-10 → 바로 2008-07-11 매수 1,070만원 · 반등 보고 2008-07-25 매수 1,055만원 · 평가일 2009-07-03
  2008-10-24 → 바로 2008-10-27 매수 1,736만원 · 반등 보고 2008-10-29 매수 1,600만원 · 평가일 2009-10-20
  2011-08-19 → 바로 2011-08-22 매수 1,837만원 · 반등 보고 2011-09-02 매수 1,650만원 · 평가일 2012-08-22
  2020-03-16 → 바로 2020-03-17 매수 1,807만원 · 반등 보고 2020-03-25 매수 1,757만원 · 평가일 2021-03-23
  2024-09-19 → 바로 2024-09-20 매수 1,404만원 · 반등 보고 2024-11-19 매수 1,562만원 · 평가일 2025-10-01

[하락 × 반등 아홉 가지 조합 — 평균 로그로 바로가 앞선 조합 수]
  국내 2007 상위 40: 9개 중 9개 (단순 평균으로는 9개 중 8개)
  국내 36: 9개 중 9개 (단순 평균으로는 9개 중 8개)
  미국 30: 9개 중 4개 (단순 평균으로는 9개 중 4개)

끝.

코드 전문

# -*- coding: utf-8 -*-
"""대형주가 크게 빠진 날 — 다음 날 바로 살까, 반등을 보고 살까 (AlgoLab · 2026-10-24)

돌리는 법: 이 파일 옆에 data_bigdrop/ 폴더를 두고  python run_bigdrop.py
표준 라이브러리만 씁니다. 가격 자료는 2026-10-23 까지 얼려 둔 야후 일봉 수정종가(날짜·종가)입니다.

빠진 날  : 종가가 직전 20거래일 최고 종가보다 20% 이상 낮아진 첫 날 t
           (같은 종목은 60거래일이 지나고, 다시 20% 안쪽으로 회복했다가 빠질 때만 다시 센다)
바로     : t 다음 거래일 종가에 산다
반등 보고: t 이후 가장 낮았던 종가에서 10% 오른 종가가 나온 날의 다음 거래일 종가에 산다
           (끝 날까지 안 나오면 현금으로 둔다)
평가     : 둘 다 '바로 산 날 + 250거래일'(약 1년) 종가로 같은 날 평가 · 사는 비용 편도 0.1% · 현금 이자 0
국내 종목은 하루 ±31% 넘는 등락을 액면분할 오류로 보고 0 으로 지운다.
"""
import csv
import math
import os

HERE = os.path.dirname(os.path.abspath(__file__))
D = os.path.join(HERE, "data_bigdrop")
H, GAP, COST, BUY0 = 250, 60, 0.001, "2005-01-01"
US = "XOM GE MSFT C BAC WMT JNJ PFE AIG MO PG JPM IBM INTC CVX WFC KO CSCO GOOG VZ AMGN PEP HD COP HPQ UPS T ORCL QCOM MRK".split()


def load(path, clean):
    d, c = [], []
    for r in csv.reader(open(path, encoding="utf-8")):
        if r and r[0][:1].isdigit() and float(r[1]) > 0:
            d.append(r[0]); c.append(float(r[1]))
    if clean:
        x = [c[0]]
        for i in range(1, len(c)):
            g = c[i] / c[i - 1] - 1
            x.append(x[-1] * (1 + (0.0 if abs(g) > 0.31 else g)))
        c = x
    return d, c


def events(d, c, X):
    out, armed, last = [], True, -10**9
    for i in range(20, len(c)):
        hi = max(c[i - 20:i])
        if d[i] >= BUY0 and armed and i - last >= GAP and c[i] <= (1 - X) * hi:
            out.append(i); last = i; armed = False
        elif not armed and c[i] > (1 - X) * hi:
            armed = True
    return out


def knee(c, t, end, Y):
    lo = c[t]
    for s in range(t, end):
        lo = min(lo, c[s])
        if c[s] >= (1 + Y) * lo:
            return s
    return None


def ma_day(c, t, end):
    for s in range(max(t, 20), end):
        if c[s] > sum(c[s - 19:s + 1]) / 20:
            return s
    return None


def ret(c, buy, end):
    if buy is None or buy >= end:
        return 1.0
    return c[end] / c[buy] * (1 - COST)


def run(sub, clean, names=None, X=0.20, Y=0.10):
    names = names or sorted(f[:-4] for f in os.listdir(os.path.join(D, sub)) if f.endswith(".csv"))
    ev = []
    for nm in names:
        d, c = load(os.path.join(D, sub, nm + ".csv"), clean)
        for t in events(d, c, X):
            end = t + 1 + H
            if end < len(c):
                s = knee(c, t, end, Y)
                wb = None if s is None else s + 1
                m = ma_day(c, t, end)
                ev.append(dict(nm=nm, day=d[t], kd=d[t + 1], wd=None if wb is None or wb >= end else d[wb],
                               wait=None if s is None else s - t, end=d[end],
                               K=ret(c, t + 1, end), W=ret(c, wb, end), M=ret(c, None if m is None else m + 1, end)))
    return ev


def won(ev):
    return sum(e["K"] > e["W"] for e in ev)


def gmean(xs):
    return math.exp(sum(math.log(x) for x in xs) / len(xs))


def median(xs):
    xs = sorted(xs); n = len(xs)
    return xs[n // 2] if n % 2 else (xs[n // 2 - 1] + xs[n // 2]) / 2


def report(title, ev):
    n, k = len(ev), won(ev)
    print(f"== {title}")
    print(f"  빠진 날 {n}번 · 1년 뒤 바로 산 쪽이 더 남은 것 {k}번 · 반등을 보고 산 쪽 {n - k}번")
    print(f"  반등을 보고 산 값이 바로 산 값보다 비쌌던 것 {k}번(같은 날 평가라 위와 같은 수)")
    print(f"  반등을 기다린 기간 가운데 값 {median([e['wait'] for e in ev if e['wait'] is not None]):.0f}거래일")
    print(f"  1,000만원 기준 1년 뒤 평균(기하): 바로 {1000 * gmean([e['K'] for e in ev]):,.0f}만원 · 반등 보고 {1000 * gmean([e['W'] for e in ev]):,.0f}만원")
    print(f"  1,000만원 기준 1년 뒤 평균(단순): 바로 {1000 * sum(e['K'] for e in ev) / n:,.0f}만원 · 반등 보고 {1000 * sum(e['W'] for e in ev) / n:,.0f}만원")
    print(f"  바로 산 쪽도 1년 뒤 산 값보다 아래였던 것 {sum(e['K'] < 1 for e in ev)}번")
    per, mon, yr = {}, {}, {}
    for e in ev:
        g = math.log(e["K"]) - math.log(e["W"])
        per.setdefault(e["nm"], []).append(g); mon.setdefault(e["day"][:7], []).append(g); yr.setdefault(e["day"][:4], []).append(g)
    f = lambda m: sum(sum(v) > 0 for v in m.values())
    print(f"  종목별 평균으로 바로가 앞선 종목 {f(per)}/{len(per)} · 달로 묶으면 {f(mon)}/{len(mon)}달 · 해로 묶으면 {f(yr)}/{len(yr)}해")
    print(f"  반등을 본 쪽이 평균으로 앞선 해: {' · '.join(y for y, v in sorted(yr.items()) if sum(v) < 0)}")
    e20 = [e for e in ev if e["day"][:4] == "2020"]
    print(f"  2020년 빠진 날 {len(e20)}번 · 반등을 보고 산 쪽이 더 남은 것 {sum(e['W'] > e['K'] for e in e20)}번")
    lk = sum(math.log(e['K']) for e in ev) / n; lw = sum(math.log(e['W']) for e in ev) / n; lm = sum(math.log(e['M']) for e in ev) / n
    print(f"  20일선 위로 올라선 걸 보고 사기(평균 로그) {lm:+.4f} — 바로 {lk:+.4f} · 반등 보고 {lw:+.4f}")


if __name__ == "__main__":
    print("대형주가 20일 최고 종가보다 20% 넘게 빠진 날 — 바로 살까, 반등(바닥 +10%)을 보고 살까 · 1년 뒤 같은 날 평가\n")
    main = run("u2007", True)
    report("국내 · 2007년 말 시가총액 상위 40종 (메인)", main)
    dev = run("kr36", True)
    report("국내 · 대형주 36종 (개발 표본)", dev)
    us = run("us30", False, US)
    report("미국 · 대형주 30종", us)
    print("\n[기준선 — 빠진 날이 아니라 아무 달 첫 거래일에, 다음 날 산 것과 11거래일 늦게 산 것]")
    for title, sub in (("국내 2007 상위 40", "u2007"), ("국내 36", "kr36")):
        n = k = 0
        for nm in sorted(f[:-4] for f in os.listdir(os.path.join(D, sub)) if f.endswith(".csv")):
            d, c = load(os.path.join(D, sub, nm + ".csv"), True)
            seen = set()
            for t in range(20, len(c)):
                if d[t] >= BUY0 and d[t][:7] not in seen:
                    seen.add(d[t][:7])
                    if t + 1 + H < len(c):
                        n += 1
                        k += c[t + 1] < c[t + 12]
        print(f"  {title}: {n:,}번 중 {k:,}번 늦게 산 값이 더 비쌌다")
    for title, ev in (("국내 2007 상위 40", main), ("국내 36", dev)):
        e8 = [e for e in ev if e["day"] >= "2008-01-01"]
        print(f"  {title} · 2008년 이후 빠진 날만: {len(e8)}번 중 {won(e8)}번 바로가 더 남음")
    print("\n[삼성전자 005930 — 빠진 날 전부 · 1,000만원 기준 1년 뒤]")
    for e in main:
        if e["nm"] == "005930":
            print(f"  {e['day']} → 바로 {e['kd']} 매수 {1000 * e['K']:,.0f}만원 · 반등 보고 {e['wd']} 매수 {1000 * e['W']:,.0f}만원 · 평가일 {e['end']}")
    print("\n[하락 × 반등 아홉 가지 조합 — 평균 로그로 바로가 앞선 조합 수]")
    for title, sub, clean, nm in (("국내 2007 상위 40", "u2007", True, None), ("국내 36", "kr36", True, None), ("미국 30", "us30", False, US)):
        w = wa = 0
        for X in (0.15, 0.20, 0.30):
            for Y in (0.05, 0.10, 0.20):
                ev = run(sub, clean, nm, X, Y)
                w += sum(math.log(e["K"]) for e in ev) > sum(math.log(e["W"]) for e in ev)
                wa += sum(e["K"] for e in ev) > sum(e["W"] for e in ev)
        print(f"  {title}: 9개 중 {w}개 (단순 평균으로는 9개 중 {wa}개)")
    print("\n끝.")

알고랩 Strategy Lab — 전략을 검증하고, 검증한 것만 자동매매로 옮깁니다. 크게 빠진 다음 날 정해 둔 대로 사는 일은 사람보다 규칙이 잘합니다. 알고랩 자동매매 살펴보기 · 전략 검증 전체 보기

과거 데이터를 돌려 본 결과이며 미래 수익을 보장하지 않습니다. 투자 판단과 책임은 본인에게 있습니다.