python4

o__o·2022년 5월 29일
0

python

목록 보기
4/5

<백테스팅이란?>

: 이전 주가의 추이에 전략을 대입해보는 것

1) 이동평균선이란?
⇒ 이전 며칠(3일, 5일, 20일, 50일 등) 간의 가격을 평균하여 움직이는 선!
⇒ 일수가 커질수록 곡선이 완만해질 수밖에 없겠죠!
2) 골든크로스
: 단기이평선이 장기이평선 뚫고올라올때! 주가가 높아질 가능성이 있다는 신호
데드크로스
: 단기이평선이 장기이평선 뚫고내려올떄! 주가가 낮아질 가능성이 있다는 신호

<주가 가져오기: 라이브러리 pandas-datareader 와 finance-datareader>

!pip install yfinance pandas-datareader finance-datareader
from pandas_datareader import data as pdr

import yfinance as yf
yf.pdr_override()

import numpy as np
import pandas as pd

import FinanceDataReader as fdr

df = fdr.DataReader('005930','2018')

df.head()

  • Open: 시초가
  • High: 고가
  • Low: 저가
  • Close: 종가
  • Volume: 거래량
  • Change: 변동

<간단한 그래프 그리기:네이버금융>

1) 주가 그래프 그려보기
.plot(y=['컬럼명'])

df = fdr.DataReader('005930','2018')
df.plot(y=['Close'])

크게그리고, 격자 추가하기

df.plot(y=['Close'],figsize=(15,8),grid=True)

2) 종목 두 개의 최근 100일 주가 변동 그래프 그려보기

df_1 = fdr.DataReader('005930','2018')
df_2 = fdr.DataReader('066570','2018')

df_tot = pd.DataFrame()
df_tot['Samsung'] = df_1[['Change']]
df_tot['LG'] = df_2[['Change']]

df_tot.tail(100).plot(figsize=(15,8))

<이동평균값 만들기 3일>
3일마다 평균 값을 구하기

df.rolling(3).mean()

df = fdr.DataReader('005930','2018')
df = df[['Close']]
df['ma'] = df.rolling(3).mean()

df

<buy sell 표시>

1) shift 를 가지고 열을 맞춰보기

⇒ 사실은 다음 날 값과, ma 값을 비교해야 하는 것!
⇒ 같은 행에 두면 넘었는지 / 안 넘었는지 쉽게 알 수 있겠죠

ma값을 한칸 내려야하니까 shift(1) 추가하기!

df = fdr.DataReader('005930','2018')
df = df[['Close']]
df['ma'] = df.rolling(3).mean().shift(1)

2) buy & sell 표기하기
⇒ 그러면, 넘었으면 buy, 아니면 sell 로 표기할 수 있겠죠!

df['action'] = np.where(df['Close'] > df['ma'], 'buy', 'sell')

<수익률 구하기>

1)실제로 사는 시점
⇒ buy → buy → buy 이면, 사는 게 아니겠죠!

⇒ 즉, buy와 sell이 바뀌는 순간이 중요!

df['action_temp'] = df['action'].shift(1)

2)사는/파는 순간을 모아볼까요!

cond1 = (df['action'] == 'buy') & (df['action'].shift(1) == 'sell')
cond2 = (df['action'] == 'sell') & (df['action'].shift(1) == 'buy')

df_buy = df[cond1]
df_sell = df[cond2]

3) 마지막은?무조건 팔아야 함! 그래야 수익율을 알 수 있겠죠

df.iloc[-1,-1] = 'sell'

<수익률구하기2>

1) 사고, 파는 시점을 붙이기
⇒ 마찬가지로 concat 을 이용하면 된답니다

좌우로 붙이려면
,axis=1 를 붙이면 되지요!

df_result = pd.concat([df_buy,df_sell],axis=1)

df_result

2) 전략 세워보기
⇒ buy 때의 Close와 sell 때의 Close 에 주목하면 되는 것

.reset_index() 붙여서 더 깔끔히보기!

df = fdr.DataReader('005930','2018')

df = df[['Close']]
df['ma'] = df.rolling(3).mean().shift(1)
df['action'] = np.where(df['Close'] > df['ma'], 'buy', 'sell')

df.iloc[-1,-1] = 'sell'

cond1 = (df['action'] == 'buy') & (df['action'].shift(1) == 'sell')
cond2 = (df['action'] == 'sell') & (df['action'].shift(1) == 'buy')

df_buy = df[cond1].reset_index()
df_sell = df[cond2].reset_index()

df_result = pd.concat([df_buy,df_sell],axis=1)
df_result

3) 수익률 구하기
⇒ 먼저 Close라는 컬럼명을 다르게 수정해줘야 값을 고를 수 있겠죠!
⇒ 그리고 수익률 = 판 값 / 산 값 을 구합니다.

df_buy = df[cond1].reset_index()
df_buy.columns = ['날짜','종가(buy)','이평값','액션']

df_sell = df[cond2].reset_index()
df_sell.columns = ['날짜','종가(sell)','이평값','액션']

df_result = pd.concat([df_buy,df_sell],axis=1)

df_result['수익률'] = df_result['종가(sell)'] / df_result['종가(buy)']

df_result

<수익률구하기3>

수익률 계산하기

⇒ 누적 곱을 볼 수 있어요(마지막값 가져오기)**

df_result[['수익률']].cumprod().iloc[-1,-1]

⇒ 1(원금)을 빼주고 100을 곱해줘야 수익률이겠죠!

(df_result[['수익률']].cumprod().iloc[-1,-1] - 1)*100

함수로 만들기

def get_return(code,n):
  df = fdr.DataReader(code,'2018')

  df = df[['Close']].copy()

  df['ma'] = df.rolling(n).mean().shift(1)

  df['action'] = np.where(df['Close'] > df['ma'], 'buy', 'sell')

  df.iloc[-1,-1] = 'sell'

  cond1 = (df['action'] == 'buy') & (df['action'].shift(1) == 'sell')
  cond2 = (df['action'] == 'sell') & (df['action'].shift(1) == 'buy')

  df_buy = df[cond1].reset_index()
  df_buy.columns = ['날짜','종가(buy)','이평값','액션']

  df_sell = df[cond2].reset_index()
  df_sell.columns = ['날짜','종가(sell)','이평값','액션']

  df_result = pd.concat([df_buy,df_sell],axis=1)

  df_result['수익률'] = df_result['종가(sell)'] / df_result['종가(buy)']

  return df_result[['수익률']].cumprod().iloc[-1,-1] - 1

< 단기/장기이평선 적용하기:rolling의 숫자변경>

def get_return_sl(code, short, long):
  df = fdr.DataReader(code,'2018')

  df = df[['Close']].copy()

  df['ma1'] = df['Close'].rolling(short).mean().shift(1)
  df['ma2'] = df['Close'].rolling(long).mean().shift(1)

  df['action'] = np.where(df['ma1'] > df['ma2'], 'buy', 'sell')

  df.iloc[-1,-1] = 'sell'

  cond1 = (df['action'] == 'buy') & (df['action'].shift(1) == 'sell')
  cond2 = (df['action'] == 'sell') & (df['action'].shift(1) == 'buy')

  df_buy = df[cond1].reset_index()
  df_buy.columns = ['날짜','종가(buy)','이평값1','이평값2','액션']

  df_sell = df[cond2].reset_index()
  df_sell.columns = ['날짜','종가(sell)','이평값1','이평값2','액션']

  df_result = pd.concat([df_buy,df_sell],axis=1)

  df_result['수익률'] = df_result['종가(sell)'] / df_result['종가(buy)']

  df_final = (df_result[['수익률']].cumprod().tail(1) - 1)*100
  df_final['단기'] = short
  df_final['장기'] = long

  return df_final

#과제

한 종목에 대해 최적의 단기/장기이평선을 구해볼까요!
⇒ 단기 며칠 / 장기 며칠이 이 종목에 가장 적절한 전략일까요!
3일~10일 / 30일~60일

이중 반복문! for in range()

def get_return_sl(code, short, long):
  df = fdr.DataReader(code,'2018')

  df = df[['Close']].copy()

  df['ma1'] = df['Close'].rolling(short).mean().shift(1)
  df['ma2'] = df['Close'].rolling(long).mean().shift(1)

  df['action'] = np.where(df['ma1'] > df['ma2'], 'buy', 'sell')

  df.iloc[-1,-1] = 'sell'

  cond1 = (df['action'] == 'buy') & (df['action'].shift(1) == 'sell')
  cond2 = (df['action'] == 'sell') & (df['action'].shift(1) == 'buy')

  df_buy = df[cond1].reset_index()
  df_buy.columns = ['날짜','종가(buy)','이평값1','이평값2','액션']

  df_sell = df[cond2].reset_index()
  df_sell.columns = ['날짜','종가(sell)','이평값1','이평값2','액션']

  df_result = pd.concat([df_buy,df_sell],axis=1)

  df_result['수익률'] = df_result['종가(sell)'] / df_result['종가(buy)']

  df_final = (df_result[['수익률']].cumprod().tail(1) - 1)*100
  df_final['단기'] = short
  df_final['장기'] = long

  return df_final

--------------------------

dfs = []
for short in range(3,11):
  for long in range(30,61):
    df = get_return_sl('005930',short,long)
    dfs.append(df)

df_result = pd.concat(dfs)
df_result.sort_values(by='수익률', ascending=False)

0개의 댓글