코스피 · 연휴 · 언제 팔까 · 실측 재현 페이지

연휴 앞 코스피,
팔고 갈까 들고 갈까

설·추석처럼 긴 연휴 앞에 코스피를 팔고 갔다가 연휴 뒤에 다시 사면 어떻게 됐을까요? 코스피 지수 실제 일봉 · 1999년 1월 4일 ~ 2026년 10월 29일(약 28년) · 1,000만원 · 사고팔 때마다 편도 0.02%(수수료+호가 차이 근사).

10,105만원연휴가 와도 그냥 들고 간 계좌
8,498만원긴 연휴(163번)마다 팔고 연휴 뒤에 다시 산 계좌
10/28해마다 따로 견줬을 때 팔고 간 쪽이 앞선 해

두 계좌 규칙 그대로

항목값
긴 연휴연휴 앞 마지막 거래일과 연휴 뒤 첫 거래일 사이가 달력으로 4일 이상(주말 포함 사흘 이상 쉼) — 설·추석, 공휴일이 주말에 붙은 때
왜 1999년부터1998년 12월 전까지는 토요일에도 장이 열렸는데 가격 자료에 토요일 가격이 없어, 그 시절의 연휴 판정을 믿을 수 없습니다
휴장일 판정평일인데 코스피·코스닥 지수 둘 다 가격이 없는 날(빈 평일이 6일을 넘으면 자료 구멍으로 보고 뺌)
팔고 가는 계좌연휴 앞 마지막 거래일 종가에 전부 팔고, 연휴 뒤 첫 거래일 종가에 다시 산다 · 쉬는 동안 이자 0
들고 가는 계좌처음에 사서 끝까지 보유
비용편도 0.02% · 세금 미반영(국내 주식형 ETF 매매차익 비과세)

결과 — 코스피 지수(배당 빠진 가격)

기간 · 비용들고 가기팔고 가기
1999-01 ~ 2026-10 · 편도 0.02%10,105만원8,498만원
같은 기간 · 수수료 010,105만원9,071만원
같은 기간 · 편도 0.1%10,105만원6,546만원
2012 ~ 2025 · 편도 0.02%2,308만원2,238만원
2012 ~ 2026-10 · 편도 0.02%3,252만원3,488만원

연휴가 끝나고 코스피가 올라 있던 때: 28년 90/163 · 1999~2011 44/69 · 2012년 이후 46/94. 팔고 간 쪽이 앞선 해(해마다 따로 견줌): 10/28 — 1999 2006 2007 2008 2014 2015 2016 2019 2020 2026. 연휴 건너기 합이 가장 나빴던 해: 2008 -15.9% · 2026 -9.7% · 2020 -6.4%.

2026년 긴 연휴 9번 중 내림 6번: 02-13→02-19 +3.09% · 02-27→03-03 -7.24% · 04-30→05-04 +5.12% · 05-22→05-26 +2.55% · 07-16→07-20 -4.46% · 08-14→08-18 -1.55% · 09-23→09-28 -2.70% · 10-02→10-06 -0.89% · 10-08→10-12 -3.65%

팔고 쉬는 동안 이자를 주면(쉰 날 합 751일): 연 3% 9,031만원 · 연 5% 9,396만원 · 연 10% 10,339만원 (들고 가기 10,105만원) — 연 8%까지는 들고 간 쪽이 앞서고, 연 10%를 내내 주면 판 쪽이 앞섭니다.

실제로 살 수 있는 ETF로 — KODEX 200(069500, 분배금 반영 가격)

기간 · 비용들고 가기팔고 가기
2009-05 ~ 2026-10-20 · 편도 0.02%6,443만원6,567만원
2009-05 ~ 2025-12 · 편도 0.02%4,488만원4,092만원

올해(2026년)까지 넣으면 팔고 간 쪽이 조금 앞섭니다. 2025년까지는 들고 간 쪽이 앞섰습니다 — 판 쪽이 앞선 것은 연휴마다 내린 올해 덕분입니다. 덧붙임: 연휴 뒤 첫날 아침 시가에 다시 사면(편도 0.1%) 4,272만원 — 연휴 뒤 첫날 낮에 내리는 경향이 있었지만 횟수가 적어 약한 근거입니다.

한계 — 먼저 읽어 주세요

받아가기

돌리는 법: zip 을 풀고 python run_holiday.py — 연휴 날짜는 코드가 가격 자료에서 직접 찾아 출력합니다.

그대로 돌린 출력

코스피 지수 1999-01-04 ~ 2026-10-29 · 긴 연휴 163번
  편도 0.00%: 들고 가기 10,105만원 · 팔고 가기 9,071만원
  편도 0.02%: 들고 가기 10,105만원 · 팔고 가기 8,498만원
  편도 0.10%: 들고 가기 10,105만원 · 팔고 가기 6,546만원
  연휴 뒤 올라 있던 때 90/163 · 1999~2011 44/69 · 2012~ 46/94
  가장 크게 오른 연휴 2002-02-08 → 2002-02-14 +7.64% · 2009-01-23 → 2009-01-28 +5.91% · 2026-04-30 → 2026-05-04 +5.12% / 가장 크게 내린 연휴 2026-02-27 → 2026-03-03 -7.24%
  팔고 간 쪽이 앞선 해 10/28: 1999 2006 2007 2008 2014 2015 2016 2019 2020 2026
  연휴 건너기 합이 가장 나빴던 해: 2008 -15.9% · 2026 -9.7% · 2020 -6.4%
  2026년 긴 연휴 9번 중 내림 6번: 02-13→02-19 +3.09% · 02-27→03-03 -7.24% · 04-30→05-04 +5.12% · 05-22→05-26 +2.55% · 07-16→07-20 -4.46% · 08-14→08-18 -1.55% · 09-23→09-28 -2.70% · 10-02→10-06 -0.89% · 10-08→10-12 -3.65%
  팔고 쉬는 동안 이자를 주면(쉰 날 합 751일): 연 3% 9,031만원 · 연 5% 9,396만원 · 연 10% 10,339만원 (들고 가기 10,105만원)
  2012~2025: 들고 가기 2,308만원 · 팔고 가기 2,238만원
  2012~2026-10: 들고 가기 3,252만원 · 팔고 가기 3,488만원

KODEX 200(069500) 2009-05-04 ~ 2026-10-20 · 긴 연휴 106번
  편도 0.00%: 들고 가기 6,443만원 · 팔고 가기 6,852만원
  편도 0.02%: 들고 가기 6,443만원 · 팔고 가기 6,567만원
  편도 0.10%: 들고 가기 6,443만원 · 팔고 가기 5,542만원
  2025년까지(0.02%): 들고 가기 4,488만원 · 팔고 가기 4,092만원
  덧붙임 — 연휴 뒤 첫날 시가에 다시 사기(편도 0.1%): 4,272만원

재현 코드 전문

# -*- coding: utf-8 -*-
"""연휴 앞 코스피 — 팔고 갈까, 들고 갈까 (AlgoLab · 2026-10-30)

표준 라이브러리만 씁니다. 같은 폴더의 가격 자료(CSV)를 읽어 영상·설명란의 숫자를 전부 다시 냅니다.
    python run_holiday.py

규칙
- 휴장일: 평일인데 가격이 없는 날. 코스피 지수는 코스닥 지수에도 가격이 없어야 휴장으로 셉니다.
- 긴 연휴: 연휴 앞 마지막 거래일과 연휴 뒤 첫 거래일 사이가 달력으로 4일 이상(주말 포함 사흘 이상 쉼).
  사이에 빈 평일이 6일을 넘으면 자료 구멍으로 보고 뺍니다.
- 팔고 가는 계좌: 연휴 앞 마지막 거래일 종가에 전부 팔고, 연휴 뒤 첫 거래일 종가에 다시 삽니다(쉬는 동안 이자 0).
- 들고 가는 계좌: 처음에 사서 끝까지 보유.
- 수수료: 편도 0.02%(수수료+호가 차이 근사). 0 · 0.1% 도 같이 냅니다.
- 시작: 1999-01-04. 국내 증시는 1998년 12월 전까지 토요일에도 장이 열렸는데 가격 자료에 토요일 봉이 없습니다.
  그 시절 '금요일 휴장'은 사흘 쉼이 아니었을 수 있어 연휴 판정을 믿을 수 없으므로 1999년부터 셉니다.
자료 끝: 코스피·코스닥 지수 2026-10-29 · KODEX 200(069500, 분배금 반영 가격) 2026-10-20
"""
import csv
import os
from datetime import date, timedelta

HERE = os.path.dirname(os.path.abspath(__file__))
ASOF = {'KS11': '2026-10-29', 'KQ11': '2026-10-29', '069500': '2026-10-20'}
START = '1999-01-01'


def load(name, cols=('close',)):
    out = []
    with open(os.path.join(HERE, name + '_1d.csv'), encoding='utf-8') as f:
        for r in csv.DictReader(f):
            if r['date'] > ASOF[name]:
                continue
            try:
                v = tuple(float(r[c]) for c in cols)
            except ValueError:
                continue
            if all(x > 0 for x in v):
                out.append((r['date'],) + v)
    return out


def events(s, other_dates=()):
    """거래일 i-1 → i 간격의 종류: long(긴 연휴) · weekend · day · other · hole"""
    out = []
    for i in range(1, len(s)):
        a, b = date.fromisoformat(s[i - 1][0]), date.fromisoformat(s[i][0])
        gap = (b - a).days
        miss = sum(1 for k in range(1, gap) if (a + timedelta(days=k)).weekday() < 5)
        if miss > 6:
            kind = 'hole'
        elif gap >= 4:
            kind = 'hole' if any((a + timedelta(days=k)).isoformat() in od for k in range(1, gap) for od in other_dates) else 'long'
        elif gap == 3 and a.weekday() == 4:
            kind = 'weekend'
        else:
            kind = 'day' if gap == 1 else 'other'
        out.append((i, kind))
    return out


def account(s, ev, sell, cost):
    eq = 1.0
    for i, k in ev:
        eq *= (1 - cost) ** 2 if sell(i, k) else s[i][1] / s[i - 1][1]
    return round(1000 * eq)  # 1,000만원 → 만원


def man(x):
    return f'{x:,}만원'


def main():
    C = 0.0002
    ks = [x for x in load('KS11') if x[0] >= START]
    kq = set(d for d, *_ in load('KQ11'))
    ev = events(ks, [kq])
    L = [i for i, k in ev if k == 'long']
    ret = lambda i: ks[i][1] / ks[i - 1][1] - 1
    hold = lambda i, k: False
    sell = lambda i, k: k == 'long'
    print(f'코스피 지수 {ks[0][0]} ~ {ks[-1][0]} · 긴 연휴 {len(L)}번')
    for c in (0, C, 0.001):
        print(f'  편도 {c*100:.2f}%: 들고 가기 {man(account(ks, ev, hold, c))} · 팔고 가기 {man(account(ks, ev, sell, c))}')
    up = sum(1 for i in L if ret(i) > 0)
    print(f'  연휴 뒤 올라 있던 때 {up}/{len(L)}'
          f' · 1999~2011 {sum(1 for i in L if ks[i][0] < "2012" and ret(i) > 0)}/{sum(1 for i in L if ks[i][0] < "2012")}'
          f' · 2012~ {sum(1 for i in L if ks[i][0] >= "2012" and ret(i) > 0)}/{sum(1 for i in L if ks[i][0] >= "2012")}')
    top = sorted(L, key=ret, reverse=True)[:3]; worst = min(L, key=ret)
    print('  가장 크게 오른 연휴 ' + ' · '.join(f'{ks[i-1][0]} → {ks[i][0]} {100*ret(i):+.2f}%' for i in top) + f' / 가장 크게 내린 연휴 {ks[worst-1][0]} → {ks[worst][0]} {100*ret(worst):+.2f}%')
    # 해마다
    yr = {}
    for i, k in ev:
        if k == 'hole':
            continue
        y = ks[i][0][:4]; r = ks[i][1] / ks[i - 1][1]
        h, v, n, s = yr.get(y, (1.0, 1.0, 0, 0.0))
        yr[y] = (h * r, v * ((1 - C) ** 2 if k == 'long' else r), n + (k == 'long'), s + (r - 1 if k == 'long' else 0))
    won = [y for y, (h, v, n, s) in sorted(yr.items()) if n and v > h]
    print(f'  팔고 간 쪽이 앞선 해 {len(won)}/{sum(1 for y in yr.values() if y[2])}: {" ".join(won)}')
    sums = sorted(((100 * s, y) for y, (h, v, n, s) in yr.items() if n))
    print('  연휴 건너기 합이 가장 나빴던 해: ' + ' · '.join(f'{y} {s:+.1f}%' for s, y in sums[:3]))
    y26 = [i for i in L if ks[i][0][:4] == '2026']
    print(f'  2026년 긴 연휴 {len(y26)}번 중 내림 {sum(1 for i in y26 if ret(i) < 0)}번: '
          + ' · '.join(f'{ks[i-1][0][5:]}→{ks[i][0][5:]} {100*ret(i):+.2f}%' for i in y26))
    # 팔고 쉬는 동안 예금 이자를 주면(쉰 달력일 × 고정 연 이율)
    days = sum((date.fromisoformat(ks[i][0]) - date.fromisoformat(ks[i - 1][0])).days for i in L)
    row = []
    for rate in (0.03, 0.05, 0.10):
        v = 1.0
        for i, k in ev:
            if k == 'long':
                d = (date.fromisoformat(ks[i][0]) - date.fromisoformat(ks[i - 1][0])).days
                v *= (1 - C) ** 2 * (1 + rate) ** (d / 365)
            else:
                v *= ks[i][1] / ks[i - 1][1]
        row.append(f'연 {int(rate*100)}% {man(round(1000 * v))}')
    print(f'  팔고 쉬는 동안 이자를 주면(쉰 날 합 {days}일): ' + ' · '.join(row) + f' (들고 가기 {man(account(ks, ev, hold, C))})')
    for lo, hi, lab in (('2012', '2026', '2012~2025'), ('2012', '2027', '2012~2026-10')):
        e = [(i, k) for i, k in ev if lo <= ks[i][0] < hi]
        print(f'  {lab}: 들고 가기 {man(account(ks, e, hold, C))} · 팔고 가기 {man(account(ks, e, sell, C))}')
    # 실제 ETF
    kd = [x for x in load('069500', ('open', 'close')) if x[0] >= '2009-05-01']
    sc = [(d, c) for d, o, c in kd]
    e2 = events(sc, [set(d for d, *_ in ks)])
    print(f'\nKODEX 200(069500) {sc[0][0]} ~ {sc[-1][0]} · 긴 연휴 {sum(1 for _, k in e2 if k == "long")}번')
    for c in (0, C, 0.001):
        print(f'  편도 {c*100:.2f}%: 들고 가기 {man(account(sc, e2, hold, c))} · 팔고 가기 {man(account(sc, e2, sell, c))}')
    e3 = [(i, k) for i, k in e2 if sc[i][0] < '2026']
    print(f'  2025년까지(0.02%): 들고 가기 {man(account(sc, e3, hold, C))} · 팔고 가기 {man(account(sc, e3, sell, C))}')
    # 연휴 뒤 첫날 아침 시가에 다시 사기(편도 0.1%)
    eq = 1.0
    for i, k in e2:
        if k == 'long':
            eq *= (1 - 0.001) ** 2 * kd[i][2] / kd[i][1]   # 시가에 사서 그날 종가까지
        else:
            eq *= kd[i][2] / kd[i - 1][2]
    print(f'  덧붙임 — 연휴 뒤 첫날 시가에 다시 사기(편도 0.1%): {man(round(1000 * eq))}')


if __name__ == '__main__':
    main()

알고랩 Strategy Lab — 전략을 검증하고, 검증한 것만 자동매매로 옮깁니다. 「연휴 앞이라고 팔지 않는다」 같은 규칙은 사람보다 정해 둔 규칙대로 도는 자동매매가 잘 지킵니다. 알고랩 자동매매 살펴보기 · 전략 검증 전체 보기

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