미국ETF 양도소득세는 복리에 어떤 영향을 미칠까?
본문 바로가기
파이썬(Python)/파이썬으로 투자실험

미국ETF 양도소득세는 복리에 어떤 영향을 미칠까?

by Squat Lee 2024. 4. 15.

미국 주식이나 ETF를 투자하면 수익을 실현한 금액에 대해서 양도소득세를 부과합니다.

 

매년 손익통산(수익과 손실을 더해서)을 한 후 수익의 250만원을 제한 나머지 금액에 22%의 양도소득세를 부과합니다.

 

22%는 적은 금액은 아니죠? 1억의 수익이 있으면 2천2백만원이 세금으로 나간다고 하니 절대 가볍게 여길 사항은 아닙니다.

 

그렇다고 국내상장 해외주식을 투자한다면 배당소득세가 부과되어 금융소득 종합과세 대상자가 되면 세율이 최고 45%까지 올라가고 건보료가 올라가는 등 여러가지 불이익이 발생합니다.

 

세금문제 참 어렵죠?

 

일단,  지난번 포스트에서 얘기한 QQQ와 SCHD의 최적의 조합에서 양도소득세를 적용하면 수익이 어떻게 바뀔지 살펴 보도록 하겠습니다.

구  분(QQQ:SCHD 비율) CAGR(%) MDD(%) 총수익률(%)
1 : 9 7.0 -32.1 126
2 : 8 7.5 -33.5 137
3: 7 7.9 -30.9 149
4 : 6 78.3 -30.4 160
5 : 5 8.7 -29.9 172
6 : 4 9.1 -29.4 184
7 : 3 9.3 -28.9 197
8 : 2 9.9 -29.0 210
9 : 1 10.3 -31.2 223

 

 

지난 포스트에서 QQQ와 SCHD의 비율별 CAGR과 MDD의 변화를 확인할 수 있었습니다. 예상과 다르게 QQQ 비율이 높아지면 CAGR은 높아지고 MDD는 낮아지는 효과를 확인할 수 있었습니다.

 

그런데 양도소득세를 고려하지 않은 결과입니다.

 

복리의 효과를 누리기 위해서는 손실이 나면 안 됩니다. 세금도 일종의 손실이기 때문에 복리수익률을 갈가먹게 됩니다.

 

백테스트 조건

1. QQQ와 SCHD를 5:5 비율로 매월 리밸런싱을 합니다.

2. 초기자산은 $2,000이고, 매월 $1,000씩 추가금이 투입됩니다.(리밸런싱은 추가금이 투입된 기준입니다.)

3. 배당수익은 재투자를 한다고 가정했습니다.

4. 매매수수료는 0.25%, 매당수수료는 15.4%를 반영했습니다.

5. 기간은 QQQ와 SCHD 중 상장일이 늦은자산을 기준으로 2023년 12월 31일까지입니다.

6. 연도별 이익과 손실을 합쳐서 250만원이 넘는 금액에 대해서는 22% 세금을 제하고 마지막날 자산을 조정하였습니다.

※ 연간 운용수수료는 ETF가격에 포함되었기에 별도로 고려하지 않았습니다.

 

양도세가 적용된 백테스트(QQQ SCHD 8:2 조건)

 

 

QQQ : SCHD(8:2조건) 양도세 적용전(%) 양도세 적용후(%)
CAGR 9.9 9.9
MDD -29.0 -29.0
총 수익률 210 210

 

재미있네요. 양도세가 적용되었는데도 CAGR, MDD, 총 수익률이 양도세가 적용되기 전과 결과값이 동일하게 나왔습니다.

 

어떻게 된 일일까요?

 

년도별 실현손익을 확인해 보도록 하겠습니다.

 

2011년 실현손익: 0.0
2012년 실현손익: 0.0
2013년 실현손익: 0.0

2014년 실현손익: 1,795.0
2015년 실현손익: 0.0
2016년 실현손익: 9,977.0
2017년 실현손익: 23,588.0
2018년 실현손익: 5,891.0
2019년 실현손익: 32,162.0
2020년 실현손익: 267,847.0
2021년 실현손익: 1,295,815.0
2022년 실현손익: 182,692.0
2023년 실현손익: 1,724,821.0

 

위의 실현손익 금액은 매도당시 원화로 환산된 금액입니다.

 

실현이익이 250만원을 넘었을때가 없었네요. 그래서 양도소득세 금액이 0원이 되었고, 양도세가 적용되지 않은 백테슽와 동일한 결과값이 나온거네요.

 

투자금액이 낮아서 그런 것 같은데 초기 투자금액을 2만달러로 하고 매월 1천달러씩 분할매수를 한다는 가정하에 다시 백테스트를 진행해 보겠습니다.

 

QQQ : SCHD(8:2조건) 양도세 적용전(%) 양도세 적용후(%)
CAGR 11.1 11.1
MDD -29.5 -29.5
총 수익률 253 253

초기투자금액 2만달러, 월1천달러 분할매수

 

양도세 적용시 백테스트(초기 2만달러, 월 1천달러)

 

이게 뭔가요? 결과가 동일하잖아요? 제가 코딩을 잘못 한걸까요?

 

연도별 실현손익을 살펴 보겠습니다.

 

2011년 실현손익: 0.0

2012년 실현손익: -595.0
2013년 실현손익: 0.0
2014년 실현손익: 6,276.0
2015년 실현손익: -3,644.0
2016년 실현손익: 17,402.0
2017년 실현손익: 55,421.0
2018년 실현손익: 61,328.0
2019년 실현손익: 69,358.0
2020년 실현손익: 428,423.0
2021년 실현손익: 1,777,776.0
2022년 실현손익: 268,412.0
2023년 실현손익: 2,311,870.0

 

금액이 다소 커졌지만 운 좋게 양도세를 피해갔습니다.

 

그럼 이번에는 초기투자금이 약 1억 3천만원인 10만달러로 하고 월1천달러씩 투자하는 조건으로 백테스트를 해 보겠습니다.

 

 

QQQ : SCHD(8:2조건) 양도세 적용전(%) 양도세 적용후(%)
CAGR 13.8 13.7
MDD -30.3 -30.3
총 수익률 369 369

초기투자금액 10만달러, 월1천달러 분할매수

 

 

이렇게 투자하니깐 CAGR이 상당히 좋아지네요. 그런데 이번에도 양도세 적용 전후가 거의 차이가 없습니다.

 

총 양도세는 $689.0 (약 879,838.0원)이 나왔습니다. 생각보다 많은 금액이 아니네요.

 

연도별 실현수익을 보도록 하겠습니다.

 

2011년 실현손익: 9,681.0
2012년 실현손익: 1,155.0
2013년 실현손익: 29,913.0
2014년 실현손익: 36,696.0
2015년 실현손익: 23,919.0
2016년 실현손익: 160,644.0
2017년 실현손익: 258,401.0
2018년 실현손익: 290,024.0
2019년 실현손익: 388,760.0
2020년 실현손익: 1,204,760.0
2021년 실현손익: 3,919,926.0

2022년 실현손익: 649,188.0
2023년 실현손익: 4,974,386.0

 

리밸런싱으로 인해 소모되는 세금이 생각보다 크지가 않네요.

 

사실 초기금액 1억으로 월 1천만원씩 투자한다는 것은 현실과 그렇게 동떨어진 조건은 아닌 것 같습니다. 대부분 이것보다 더 작은금액을 투자하곤 합니다. 

 

그런데 사람들은 해외 양도세 때문에 마치 큰 손해를 볼거라고 생각을 하더라구요. 실제적으로 이렇게 백테스트 해 보니깐 생각보다 세금이 크지 않다는 사실을 알게 되었습니다.

 

그런데 나중에 금액이 10억이상 불어난다면 다른 얘기가 되겠죠? 

 

같은 금액으로 초기 금액을 100만달러(약 13억원)으로 설정한다면 양도세 총계는 $12,788.0 (약 16,340,869.0원)가 됩니다. 

 

하지만 백테스트 기간동안 자산은 6.58배로 늘어나며, 초기투자금액 13억에서 86억 7천2백만원 정도로 불어납니다.

 

이정도 불었는데 양도소득세가 16억원이 많아 보이나요? 저는 양도소득세 때문에 미국주식투자를 하지 못할 것 같지는 않습니다.

 


지금까지는 자산비율을 동일하게 유지하면서 투자하는 방법으로 백테스트를 하였습니다.

 

그러면 주식이 올라갈때 더 많이 사고, 떨어질 때 비중을 줄이는 방법인 동적자산배분으로 투자를 한다면 결과가 어떻게 나올까요?

 

다음 포스트에서 다뤄보도록 하겠습니다.

 

 

백테스트 코드

import pandas as pd
from pandas_datareader import data as pdr
import yfinance as yf
yf.pdr_override()
from datetime import datetime
import numpy as np
import matplotlib.pyplot as plt

pd.options.display.float_format = '{:,.2f}'.format

#투자자산
p1 = 'QQQ'
p2 = 'SCHD'

p1비율 = 0.8

def get_div(p):
    ticker1 = yf.Ticker(p)
    div = ticker1.dividends.tz_localize(None)
    return div


매매수수료 = 0.0025
배당소득세 = 0.154

start = datetime(2005, 1, 1)
end = datetime(2023, 12, 31)

초기투자금 = 1000000
매월투자금 = 1000

배당금적용여부 = 1 #1이면 적용, 0이면 미적용

#데이터 가져오기
def get_data(p1, p2, start, end):
    df1 = pdr.get_data_yahoo(p1, start, end)
    df1.rename(columns={'Adj Close':'p1주가'}, inplace=True)

    df2 = pdr.get_data_yahoo(p2, start, end)
    df2.rename(columns={'Adj Close':'p2주가'}, inplace=True)

    df_ex = pdr.get_data_yahoo('USDKRW=X', start, end) #환율
    df_ex.rename(columns={'Adj Close': '환율'}, inplace=True)

    df = pd.merge(df1['p1주가'], df2['p2주가'], left_index=True, right_index=True, how='inner')
    df = pd.merge(df, df_ex['환율'], left_index=True, right_index=True)
    return df


# 세금계산을 위해서 년도별 마지막날 구하기
df_y = get_data(p1, p2, start, end)
df_y['date'] = df_y.index
df_y = df_y.groupby(by=df_y.index.year).last()
li_lastdays = df_y['date'].to_list()

# 배당데이터에 다른 데이터 넣기
def merge_div(p1, p2, start, end):
    df = get_data(p1, p2, start, end)
    div1 = get_div(p1)
    div2 = get_div(p2)
    if 배당금적용여부 == 1:
        df['배당금1'] = div1
        df['배당금2'] = div2
        df.fillna(0, inplace=True)
    else:
        df['배당금1'] = 0
        df['배당금2'] = 0
    return df

df = merge_div(p1, p2, start, end)

#월말투자금 넣기
df_m = df
df_m['date'] = df_m.index #멀티인덱스로 만들어지기에 별도의 날짜컬럼을 만들고
df_m = df_m.groupby(by=[df.index.year, df.index.month]).last() #매월 마지막날만 필터
li_monthlast = df_m['date'].to_list()

df['투자금'] = 0
for i, m in enumerate(li_monthlast):
    if i == 0:
        df['투자금'].loc[m] = 초기투자금
    else:
        df['투자금'].loc[m] = 매월투자금

#MDD 구하기
def get_mdd(col):
    window = 252
    peak = col.rolling(window, min_periods=1).max()
    drawdown = col/peak -1
    연도별mdd = drawdown.rolling(window, min_periods=1).min()
    mdd = 연도별mdd.min()
    return mdd

# 적립식 투자하면서 자산변동 계산
df[['p1주식수', 'p1금액', 'p2주식수', 'p2금액', '합계', '원금누계', '실현손익', '연간양도세']] = 0
for m in range(len(df)):
    if m == 0:
        df['합계'].iloc[m] = df['투자금'].iloc[m] * (1-매매수수료)
        df['p1금액'].iloc[m] = df['합계'].iloc[m] * p1비율
        df['p1주식수'].iloc[m] = df['p1금액'].iloc[m] / df['p1주가'].iloc[m]
        df['p2금액'].iloc[m] = df['합계'].iloc[m] - df['p1금액'].iloc[m]
        df['p2주식수'].iloc[m] = df['p2금액'].iloc[m] / df['p2주가'].iloc[m]
        df['원금누계'].iloc[m] = df['투자금'].iloc[m]
        df['실현손익'].iloc[m] = 0
    else:
        df['합계'].iloc[m] = df['투자금'].iloc[m] * (1-매매수수료) + \
                           (df['p1주가'].iloc[m] * df['p1주식수'].iloc[m-1]) + (df['p2주가'].iloc[m] * df['p2주식수'].iloc[m-1]) + \
                           (df['배당금1'].iloc[m] * df['p1주식수'].iloc[m-2] + df['배당금2'].iloc[m] * df['p2주식수'].iloc[m-2]) * (1 - 배당소득세)
        # 매월 리밸런싱 할 때는 주식수가 변하지만
        if df['투자금'].iloc[m] > 0:
            df['p1금액'].iloc[m] = df['합계'].iloc[m] * p1비율
            df['p1주식수'].iloc[m] = df['p1금액'].iloc[m] / df['p1주가'].iloc[m]
            df['p2금액'].iloc[m] = df['합계'].iloc[m] - df['p1금액'].iloc[m]
            df['p2주식수'].iloc[m] = df['p2금액'].iloc[m] / df['p2주가'].iloc[m]
        # 리밸런싱을 안 하는 날에는 주식수가 고정
        else:
            df['p1주식수'].iloc[m] = df['p1주식수'].iloc[m-1]
            df['p1금액'].iloc[m] = df['p1주식수'].iloc[m] * df['p1주가'].iloc[m]
            df['p2주식수'].iloc[m] = df['p2주식수'].iloc[m - 1]
            df['p2금액'].iloc[m] = df['p2주식수'].iloc[m] * df['p2주가'].iloc[m]
        df['원금누계'].iloc[m] = df['원금누계'].iloc[m - 1] + df['투자금'].iloc[m]
            # 매월 리밸런싱 할때 실현손익 구하기
        if df['투자금'].iloc[m] > 0 and m > 0:
            for j in range(1, 33):
                if df['투자금'].iloc[m-j] > 0:
                    if df['p1주식수'].iloc[m] < df['p1주식수'].iloc[m-j]:
                        df['실현손익'].iloc[m] = (df['p1주식수'].iloc[m-j]-df['p1주식수'].iloc[m]) * \
                                             (df['p1주가'].iloc[m] - df['p1주가'].iloc[m-j]) - \
                                             (df['p1주식수'].iloc[m-j]-df['p1주식수'].iloc[m]) * df['p1주가'].iloc[m] * 매매수수료
                    if df['p2주식수'].iloc[m] < df['p2주식수'].iloc[m - j]:
                        df['실현손익'].iloc[m] = (df['p2주식수'].iloc[m-j]-df['p2주식수'].iloc[m]) * \
                                             (df['p2주가'].iloc[m] - df['p2주가'].iloc[m-j]) -\
                                             (df['p2주식수'].iloc[m-j]-df['p2주식수'].iloc[m]) * df['p2주가'].iloc[m] * 매매수수료
                        break

        else:
            df['실현손익'].iloc[m] = 0

        # 실현손익으로 양도소득세 계산 및 합계, 주식금액을 양도소득세를 제외한 금액으로 정정
        if df.index[m] in li_lastdays:
            연간실현손익 = df['실현손익'].loc[str(df.index[m])[:4]].sum() * df['환율'].iloc[m] #원화로 변환
            print(f'{str(df.index[m])[:4]}년 실현손익: {round(연간실현손익,0):,}')
            if 연간실현손익 >= 2500000:
                df['연간양도세'].iloc[m] = ((연간실현손익 - 2500000) * 0.22)/df['환율'].iloc[m] #달러로 변환
                print(f"{df['연간양도세'].index[m]}연간양도세 : {df['연간양도세'].iloc[m]}")
                df['합계'].iloc[m] = df['투자금'].iloc[m] * (1 - 매매수수료) + \
                                   (df['p1주가'].iloc[m] * df['p1주식수'].iloc[m - 1]) + (
                                               df['p2주가'].iloc[m] * df['p2주식수'].iloc[m - 1]) + \
                                   (df['배당금1'].iloc[m] * df['p1주식수'].iloc[m - 2] + df['배당금2'].iloc[m] *
                                    df['p2주식수'].iloc[m - 2]) * (1 - 배당소득세) - df['연간양도세'].iloc[m]
                df['p1금액'].iloc[m] = df['합계'].iloc[m] * p1비율
                df['p1주식수'].iloc[m] = df['p1금액'].iloc[m] / df['p1주가'].iloc[m]
                df['p2금액'].iloc[m] = df['합계'].iloc[m] - df['p1금액'].iloc[m]
                df['p2주식수'].iloc[m] = df['p2금액'].iloc[m] / df['p2주가'].iloc[m]


df = df[['p1주가', 'p1주식수', 'p1금액', '배당금1', 'p2주가', 'p2주식수', 'p2금액', '배당금2', '투자금', '합계', '원금누계', '실현손익', '환율', '연간양도세']]

# 2가지 자산의 누적수익률을 비교하기 위해 백분율로 표현
df['주가백분율1'] = df['p1주가'] / df['p1주가'].iloc[0]
df['주가백분율2'] = df['p2주가'] / df['p2주가'].iloc[0]
df['전략백분율'] = df['합계'] / df['원금누계']

df.dropna(inplace=True)

#CAGR
diff = df.index[-1].year - df.index[0].year
cagr_etf1 = (df['p1주가'].iloc[-1] / df['p1주가'].iloc[0]) ** (1 / diff) - 1
cagr_etf2 = (df['p2주가'].iloc[-1] / df['p2주가'].iloc[0]) ** (1 / diff) - 1
cagr_전략 = (df['합계'].iloc[-1] / df['합계'].iloc[0]) ** (1 / diff) - 1
cagr_전략_실질 = (df['합계'].iloc[-1] / df['원금누계'].iloc[-1]) ** (1 / diff) - 1
cagr = f'CAGR(ETF1) : {round(cagr_etf1, 3)} / CAGR(ETF2) : {round(cagr_etf2, 3)} / ' \
       f'CAGR(전략) : {round(cagr_전략, 3)} CAGR(실질전략) : {round(cagr_전략_실질, 3)}'
print(cagr)

#MDD구하기
mdd_etf1 = get_mdd(df['p1주가'])
mdd_etf2 = get_mdd(df['p2주가'])
mdd_전략 = get_mdd(df['합계'])
mdd_t = f'MDD({p1}) : {round(mdd_etf1,3)} / MDD({p2}) : {round(mdd_etf2,3)} / MDD(전략) : {round(mdd_전략,3)}'
print(mdd_t)

ETF1수익률 = df['p1주가'].iloc[-1]/df['p1주가'].iloc[0] - 1
ETF2수익률 = df['p2주가'].iloc[-1]/df['p2주가'].iloc[0] - 1
전략수익률 = df['합계'].iloc[-1]/df['투자금'].sum() - 1

print(f'{p1} 수익률 : {round(ETF1수익률,2)}')
print(f'{p2} 수익률 : {round(ETF2수익률,2)}')
print(f'전략 수익률 : {round(전략수익률,2)}')

print(f'양도소득세 총계 : ${round(df["연간양도세"].sum(),0):,} (약 {round(df["연간양도세"].sum()*df["환율"].iloc[-1],0):,}원)')

#그래프로 표현하기
plt.rcParams['figure.figsize'] = (16, 9)

plt.plot(df.index, df['주가백분율1'], color='blue', label=p1)
plt.plot(df.index, df['주가백분율2'], color='green', label=p2)
plt.plot(df.index, df['전략백분율'], color='red', label='strategy')
plt.grid(True)
plt.legend(loc='best')

plt.title(f'{p1} {p2} {round(p1비율*10,0)}:{round((1-p1비율)*10,0)} Static Ratio Invest')

plt.show()

#엑셀파일로 만들기
df.to_excel(f'정적분배 백테스트(세금포함, {p1}({round(p1비율*10,0)}) {p2}({round((1-p1비율)*10,0)}) CAGR {round(cagr_전략_실질*100,1)} '
            f'MDD {round(mdd_전략*100,1)}).xlsx')

 

 

 

728x90
반응형

댓글