๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

์นดํ…Œ๊ณ ๋ฆฌ ์—†์Œ

ํŒŒ์ด์ฌ์œผ๋กœ ์‰ฝ๊ฒŒ ๋ฐฐ์›Œ๋ณด๋Š” ์ฃผ์‹ ์ž๋™๋งค๋งค ์‹œ์Šคํ…œ ๋งŒ๋“ค๊ธฐ

์‰ฝ๊ฒŒ ๋”ฐ๋ผ ๋งŒ๋“œ๋Š” ํŒŒ์ด์ฌ ์ฃผ์‹ ์ž๋™๋งค๋งค ์‹œ์Šคํ…œ

์ฃผ์‹ ํˆฌ์ž์— ๊ด€์‹ฌ์ด ์žˆ์ง€๋งŒ ์‹œ๊ฐ„์„ ๋‚ด๊ธฐ ์–ด๋ ค์šด ์ด๋“ค์„ ์œ„ํ•ด, ์ž๋™์œผ๋กœ ๋งค๋งค๋ฅผ ์ง„ํ–‰ํ•˜๋Š” ์‹œ์Šคํ…œ์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฒˆ ํฌ์ŠคํŠธ์—์„œ๋Š” python์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ„๋‹จํ•œ ์ฃผ์‹ ์ž๋™๋งค๋งค ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•˜๋Š” ๊ณผ์ •์„ ๋‹จ๊ณ„๋ณ„๋กœ ์•ˆ๋‚ดํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ค€๋น„ ์‚ฌํ•ญ

  1. ํŒŒ์ด์ฌ ์„ค์น˜: ์‹œ์Šคํ…œ์„ ๊ฐœ๋ฐœํ•˜๊ธฐ ์œ„ํ•ด ๋จผ์ € ํŒŒ์ด์ฌ์„ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Python.org์—์„œ ์ตœ์‹  ๋ฒ„์ „์„ ๋‹ค์šด๋กœ๋“œํ•˜์—ฌ ์„ค์น˜ํ•˜์„ธ์š”.

  2. ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜: ์ฃผ์‹ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด pandas, numpy, matplotlib, yfinance ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์ด pip ๋ช…๋ น์–ด๋กœ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    pip install pandas numpy matplotlib yfinance
  3. ํŠธ๋ ˆ์ด๋”ฉ API: ์‹ค์ œ ๋งค๋งค๋ฅผ ํ•˜๋ ค๋ฉด ๋ธŒ๋กœ์ปค์˜ API๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. Alpaca, Interactive Brokers ๋“ฑ ๋‹ค์–‘ํ•œ ์„ ํƒ์ง€๊ฐ€ ์žˆ์œผ๋‹ˆ ๋ณธ์ธ์ด ์„ ํ˜ธํ•˜๋Š” ๋ธŒ๋กœ์ปค์˜ API๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.

์ฃผ์‹ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘

์ฃผ์‹ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜๊ธฐ ์œ„ํ•ด yfinance๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋กœ ํŠน์ • ์ข…๋ชฉ์˜ ๊ณผ๊ฑฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import yfinance as yf

# ํŠน์ • ์ข…๋ชฉ์˜ ๋ฐ์ดํ„ฐ ๋‹ค์šด๋กœ๋“œ
ticker = 'AAPL'  # ์• ํ”Œ ์ฃผ์‹
data = yf.download(ticker, start='2020-01-01', end='2023-01-01', interval='1d')
print(data.head())

์œ„์˜ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์• ํ”Œ ์ฃผ์‹์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ „๋žต ์„ค์ •

์ด์ œ ๋งค๋งค ์ „๋žต์„ ์„ค์ •ํ•  ์ฐจ๋ก€์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ด๋™ ํ‰๊ท ์„ ์ด์šฉํ•œ ์ „๋žต์„ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์งง์€ ๊ธฐ๊ฐ„์˜ ์ด๋™ ํ‰๊ท ์„ ์ด ๊ธด ๊ธฐ๊ฐ„์˜ ์ด๋™ ํ‰๊ท ์„ ์„ ์ƒํ–ฅ ๋ŒํŒŒํ•  ๋•Œ ๋งค์ˆ˜ํ•˜๊ณ , ํ•˜ํ–ฅ ๋ŒํŒŒํ•  ๋•Œ ๋งค๋„ํ•˜๋Š” ์ „๋žต์ž…๋‹ˆ๋‹ค.

# ์ด๋™ ํ‰๊ท  ๊ณ„์‚ฐ
data['Short_MA'] = data['Close'].rolling(window=20).mean()
data['Long_MA'] = data['Close'].rolling(window=50).mean()

# ๋งค๋งค ์‹ ํ˜ธ ์ƒ์„ฑ
data['Signal'] = 0
data['Signal'][20:] = np.where(data['Short_MA'][20:] > data['Long_MA'][20:], 1, 0)
data['Position'] = data['Signal'].diff()

๋งค๋งค ์‹คํ–‰

์ด์ œ ์ค€๋น„ํ•œ ์ „๋žต์— ๋”ฐ๋ผ ์‹ค์ œ ๋งค๋งค๋ฅผ ์‹คํ–‰ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ฃผ์˜ํ•  ์ ์€ ์ด ์˜ˆ์ œ ์ฝ”๋“œ๋Š” ๊ฐ€์ƒ์˜ ๋งค๋งค๋ฅผ ์œ„ํ•œ ๊ฒƒ์ด๊ณ , ์‹ค์ œ ๊ฑฐ๋ž˜๋ฅผ ์ง„ํ–‰ํ•˜๋ ค๋ฉด ๋ฐ˜๋“œ์‹œ ์ถฉ๋ถ„ํ•œ ํ…Œ์ŠคํŠธ์™€ ๊ฒ€์ฆ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

import requests

API_URL = 'https://api.yourbroker.com/v1/orders'
API_KEY = 'your_api_key'
headers = {'Authorization': f'Bearer {API_KEY}'}

for index, row in data.iterrows():
    if row['Position'] == 1:
        # ๋งค์ˆ˜ ์ฃผ๋ฌธ
        order_data = {"symbol": ticker, "qty": 1, "side": "buy", "type": "market"}
        response = requests.post(API_URL, json=order_data, headers=headers)
        print(f'Buy Order placed: {response.json()}')
    elif row['Position'] == -1:
        # ๋งค๋„ ์ฃผ๋ฌธ
        order_data = {"symbol": ticker, "qty": 1, "side": "sell", "type": "market"}
        response = requests.post(API_URL, json=order_data, headers=headers)
        print(f'Sell Order placed: {response.json()}')

๊ฒฐ๋ก 

์ฃผ์‹ ์ž๋™๋งค๋งค ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•˜๋Š” ๊ณผ์ •์€ ์ƒ๊ฐ๋ณด๋‹ค ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ์œ„์˜ ์˜ˆ์ œ ์ฝ”๋“œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ณธ์ธ๋งŒ์˜ ์ „๋žต์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ฃผ์‹ ๊ฑฐ๋ž˜๋Š” ๋†’์€ ๋ฆฌ์Šคํฌ๊ฐ€ ๋”ฐ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์‹ ์ค‘ํ•˜๊ฒŒ ์ ‘๊ทผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ „๋žต์„ ๊ฐœ์„ ํ•˜๊ณ  ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ํ…Œ์ŠคํŠธํ•ด๋ณด๋ฉฐ ์—ฌ๋Ÿฌ๋ถ„๋งŒ์˜ ์„ฑ๊ณต์ ์ธ ์ž๋™๋งค๋งค ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค์–ด ๋ณด์„ธ์š”!

์ด์ œ ์—ฌ๋Ÿฌ๋ถ„๋„ ์ง์ ‘ ํŒŒ์ด์ฌ์œผ๋กœ ์ฃผ์‹ ์ž๋™๋งค๋งค ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค. ํˆฌ์ž ์ƒํ™œ์— ๋งŽ์€ ๋„์›€์ด ๋˜๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.