๐Ÿ’น ํ‚ค์›€์ฆ๊ถŒ OpenAPI๋กœ ์ž๋™๋งค๋งค ํ™˜๊ฒฝ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ• (ํŒŒ์ด์ฌ์œผ๋กœ ๊ตฌํ˜„ํ•˜๋Š” ๊ฐœ์ธ ํˆฌ์ž์ž์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํŠธ๋ ˆ์ด๋”ฉ ์ž…๋ฌธ์„œ)

1๏ธโƒฃ ์ž๋™๋งค๋งค์˜ ์‹œ๋Œ€, ์™œ ํ‚ค์›€์ฆ๊ถŒ OpenAPI์ธ๊ฐ€

์ตœ๊ทผ ๋ช‡ ๋…„ ์‚ฌ์ด ๊ฐœ์ธ ํˆฌ์ž์ž๋“ค ์‚ฌ์ด์—์„œ โ€˜์ฃผ์‹ ์ž๋™๋งค๋งค ์‹œ์Šคํ…œโ€™ ์— ๋Œ€ํ•œ ๊ด€์‹ฌ์ด ๊ธ‰๊ฒฉํžˆ ๋†’์•„์กŒ์Šต๋‹ˆ๋‹ค.ย  ํŠนํžˆ ํŒŒ์ด์ฌ(Python)์„ ์ด์šฉํ•œ ์ž๋™๋งค๋งค๋Š” ์ดˆ๋ณด์ž๋„ ๋น„๊ต์  ์‰ฝ๊ฒŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ณ ,ย  ๊ฐ์ •์ด ๋ฐฐ์ œ๋œ ๊ทœ์น™์  ๊ฑฐ๋ž˜๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ด ํˆฌ์ž ํšจ์œจ์„ ๊ทน๋Œ€ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋•Œ ํ•„์ˆ˜์ ์ธ ๋„๊ตฌ๊ฐ€ ๋ฐ”๋กœ ํ‚ค์›€์ฆ๊ถŒ OpenAPI+ ์ž…๋‹ˆ๋‹ค.ย  ์ด๋Š” ํ‚ค์›€์ฆ๊ถŒ์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ณต์‹ ๊ฐœ๋ฐœ์ž ์ธํ„ฐํŽ˜์ด์Šค๋กœ,ย  HTS(์˜์›…๋ฌธ4)์™€ ์—ฐ๋™ํ•ด ์ž๋™์œผ๋กœ ์ข…๋ชฉ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๊ณ , ์ฃผ๋ฌธ์„ ์‹คํ–‰ํ•˜๋ฉฐ, ์‹ค์‹œ๊ฐ„ ์ฒด๊ฒฐ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.ย  ์ฆ‰, ์‚ฌ๋žŒ์ด ํด๋ฆญํ•˜์ง€ ์•Š์•„๋„ ํŒŒ์ด์ฌ ์ฝ”๋“œ๊ฐ€ ์ž๋™์œผ๋กœ ๋งค๋งค๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ์‹œ์Šคํ…œ์ด์ฃ .

2๏ธโƒฃ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์ค€๋น„

์ž๋™๋งค๋งค๋ฅผ ์œ„ํ•œ ๊ธฐ๋ณธ ์ค€๋น„๋ฌผ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ํŒŒ์ด์ฌ 3.9 ์ด์ƒ : ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ตฌํ˜„ ์–ธ์–ด

  • ํ‚ค์›€์ฆ๊ถŒ ๊ณ„์ขŒ ๋ฐ ์˜์›…๋ฌธ4 ์„ค์น˜

  • ํ‚ค์›€์ฆ๊ถŒ OpenAPI+ : ์ž๋™์ฃผ๋ฌธ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” ํ•ต์‹ฌ ํ”„๋กœ๊ทธ๋žจ

  • PyQt5, pandas, numpy, pykiwoom : ๋ฐ์ดํ„ฐ ๋ถ„์„ ๋ฐ API ํ˜ธ์ถœ์šฉ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

  • VPS(๊ฐ€์ƒ ์„œ๋ฒ„) : 24์‹œ๊ฐ„ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ํด๋ผ์šฐ๋“œ ํ™˜๊ฒฝ (AWS, Oracle, ์นดํŽ˜24 ๋“ฑ)

์„ค์น˜๊ฐ€ ๋๋‚ฌ๋‹ค๋ฉด, ํ‚ค์›€์ฆ๊ถŒ ํ™ˆํŽ˜์ด์ง€์—์„œ โ€œOpenAPI+ ์‹ ์ฒญโ€์„ ์™„๋ฃŒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.ย  ์Šน์ธ ํ›„ KOA Studio๋ฅผ ํ†ตํ•ด API ์—ฐ๊ฒฐ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•˜์„ธ์š”.

3๏ธโƒฃ ํŒŒ์ด์ฌ๊ณผ OpenAPI ์—ฐ๊ฒฐํ•˜๊ธฐ

ํ‚ค์›€์ฆ๊ถŒ OpenAPI๋Š” COM(Component Object Model) ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.ย  ์ฆ‰, ๋‹จ์ˆœํ•œ ์›น API๊ฐ€ ์•„๋‹Œ HTS ๋‚ด๋ถ€ ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ์ œ์–ดํ•˜๋Š” ๊ตฌ์กฐ์ด๊ธฐ ๋•Œ๋ฌธ์—ย  Windows ํ™˜๊ฒฝ์—์„œ๋งŒ ๊ตฌ๋™๋˜๋ฉฐ, PyQt5๋ฅผ ํ†ตํ•ด ๋ฉ”์‹œ์ง€ ์ด๋ฒคํŠธ๋ฅผ ์ฃผ๊ณ ๋ฐ›์Šต๋‹ˆ๋‹ค.

from pykiwoom.kiwoom import Kiwoom

kiwoom = Kiwoom()
kiwoom.CommConnect()

print(“์ ‘์† ์ƒํƒœ:”, kiwoom.GetConnectState())

GetConnectState()๊ฐ€ 1์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด ์ •์ƒ์ ์œผ๋กœ ๋กœ๊ทธ์ธ๋œ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.
์ดํ›„ block_request()๋‚˜ SendOrder() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ ์กฐํšŒ ๋ฐ ์ฃผ๋ฌธ ๊ธฐ๋Šฅ์„ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

4๏ธโƒฃ ์กฐ๊ฑด๊ฒ€์ƒ‰์‹ ๋ฐ ์ „๋žต ์„ค์ •

์ž๋™๋งค๋งค์˜ ํ•ต์‹ฌ์€ ๋งค์ˆ˜ยท๋งค๋„ ์กฐ๊ฑด์„ ์–ผ๋งˆ๋‚˜ ์ •๊ตํ•˜๊ฒŒ ์„ค๊ณ„ํ•˜๋А๋ƒ์ž…๋‹ˆ๋‹ค.ย  ์˜ˆ๋ฅผ ๋“ค์–ด RSI๋‚˜ ์ด๋™ํ‰๊ท ์„ ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ „๋žต์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • RSI๊ฐ€ 30 ์ดํ•˜ โ†’ ๋งค์ˆ˜ ์‹ ํ˜ธ

  • RSI๊ฐ€ 70 ์ด์ƒ โ†’ ๋งค๋„ ์‹ ํ˜ธ

  • 5์ผ์„ ์ด 20์ผ์„ ์„ ์ƒํ–ฅ ๋ŒํŒŒ โ†’ ๊ณจ๋“ ํฌ๋กœ์Šค ๋งค์ˆ˜

์ด๋Ÿฐ ์กฐ๊ฑด์„ ํ‚ค์›€ OpenAPI์˜ GetConditionNameList() ์™€ SendCondition() ํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•ด ์ž๋™์œผ๋กœ ์ข…๋ชฉ์„ ํƒ์ƒ‰ํ•˜๊ณ  ๊ฑฐ๋ž˜๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

5๏ธโƒฃ ๋ฐฑํ…Œ์ŠคํŠธ๋กœ ์ „๋žต ๊ฒ€์ฆํ•˜๊ธฐ

์–ด๋–ค ์ „๋žต์ด๋“  ์‹ค์ „ ๋งค๋งค ์ „์— ๋ฐฑํ…Œ์ŠคํŠธ(Backtest) ๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.ย  ๊ณผ๊ฑฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์™€ ๋™์ผํ•œ ์ „๋žต์„ ์ ์šฉํ•˜๊ณ , ์ˆ˜์ต๋ฅ ยท์†์ต๋น„ยท์ตœ๋Œ€ ๋‚™ํญ ๋“ฑ์„ ๊ฒ€์ฆํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

def backtest(data):
buy, sell, profit = 0, 0, []
for i in range(1, len(data)):
if data['RSI'][i-1] < 30 and not buy:
buy = data['close'][i]
elif data['RSI'][i-1] > 70 and buy:
sell = data['close'][i]
profit.append((sell - buy) / buy)
buy = 0
return sum(profit) / len(profit)

๊ฒ€์ฆ ๊ฒฐ๊ณผ๊ฐ€ ์•ˆ์ •์ ์ด๋ผ๋ฉด, ๊ทธ ์ „๋žต์„ ์‹ค์ „ ์ž๋™๋งค๋งค์— ์ ์šฉํ•˜์„ธ์š”.

6๏ธโƒฃ VPS ์„ค์ • ๋ฐ 24์‹œ๊ฐ„ ์ž๋™ ์‹คํ–‰

์ž๋™๋งค๋งค ์‹œ์Šคํ…œ์€ ์žฅ์ค‘๋ฟ ์•„๋‹ˆ๋ผ ์žฅ ์‹œ์ž‘ ์ „ ์ค€๋น„, ์žฅ ๋งˆ๊ฐ ํ›„ ์ •์‚ฐ๊นŒ์ง€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.ย  ๋”ฐ๋ผ์„œ PC๋ฅผ ๊ณ„์† ์ผœ๋‘˜ ์ˆ˜ ์—†๋‹ค๋ฉด VPS(๊ฐ€์ƒ ์„œ๋ฒ„) ๋ฅผ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

VPS๋Š” ์›๊ฒฉ ์ ‘์† ๊ฐ€๋Šฅํ•œ 24์‹œ๊ฐ„ ์„œ๋ฒ„๋กœ,ย  ํŒŒ์ด์ฌ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์—…๋กœ๋“œํ•ด python main.py ๋ช…๋ น์œผ๋กœ ์‹คํ–‰ํ•˜๋ฉด ์ปดํ“จํ„ฐ๋ฅผ ๊บผ๋„ ๋งค๋งค๊ฐ€ ์ง€์†๋ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก ํŒ: ์œˆ๋„์šฐ ์„œ๋ฒ„ 2019 ์ด์ƒ์„ ์‚ฌ์šฉํ•˜๋ฉด OpenAPI ์•ˆ์ •์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค.

7๏ธโƒฃ ๋ฆฌ์Šคํฌ ๊ด€๋ฆฌ์™€ ๋ชจ๋‹ˆํ„ฐ๋ง

์ž๋™๋งค๋งค๋Š” โ€˜๋ฐฉ์น˜ํ˜• ์ˆ˜์ต๊ธฐ๊ณ„โ€™๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.ย  ์‹œ์žฅ ๊ธ‰๋ฝ, ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜, ๋ฐ์ดํ„ฐ ๋ˆ„๋ฝ ๋“ฑ์— ๋Œ€๋น„ํ•ดย  ๋ฆฌ์Šคํฌ ๊ด€๋ฆฌ ์ฝ”๋“œ๋ฅผ ๋ฐ˜๋“œ์‹œ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ์†์ ˆยท์ต์ ˆ ํ•œ๋„ ์„ค์ •

  • ๊ฑฐ๋ž˜๋Ÿ‰ ๊ธ‰๋“ฑ ์‹œ ์ž๋™ ์ผ์‹œ์ •์ง€

  • ๊ฑฐ๋ž˜ ๋‚ด์—ญ ๋กœ๊ทธ ์ž๋™ ์ €์žฅ

  • ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์‹œ ์•Œ๋ฆผ ์ „์†ก(Slack, ๋ฌธ์ž ๋“ฑ)

์ด๋Ÿฐ ์•ˆ์ „์žฅ์น˜๋ฅผ ๋„ฃ์œผ๋ฉด ์‹œ์Šคํ…œ์ด ์žฅ๊ธฐ์ ์œผ๋กœ ์•ˆ์ •๋ฉ๋‹ˆ๋‹ค.

๐Ÿ๊ฒฐ๋ก 

ํ‚ค์›€์ฆ๊ถŒ OpenAPI์™€ ํŒŒ์ด์ฌ์„ ํ™œ์šฉํ•˜๋ฉด ๊ฐœ์ธ ํˆฌ์ž์ž๋„ ๊ธฐ๊ด€๊ธ‰ ์ž๋™๋งค๋งค๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.ย  ํ•˜์ง€๋งŒ ํ•ต์‹ฌ์€ ์ฝ”๋“œ๊ฐ€ ์•„๋‹Œ ์ „๋žต,
์ฆ‰ ๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜์˜ ๊พธ์ค€ํ•œ ๊ฐœ์„ ์ž…๋‹ˆ๋‹ค.

์ž๋™๋งค๋งค๋Š” โ€œ๋ˆ์„ ๋Œ€์‹  ๋ฒŒ์–ด์ฃผ๋Š” ๊ธฐ๊ณ„โ€๊ฐ€ ์•„๋‹ˆ๋ผ,ย  ๋‚ด ํˆฌ์ž ์ฒ ํ•™์„ ์ž๋™ํ™”ํ•œ ์‹œ์Šคํ…œ์ด๋ผ๋Š” ์ ์„ ์žŠ์ง€ ๋งˆ์„ธ์š”.

๐Ÿ“ ์ž‘์„ฑ: ํ‹ฐ์Šคํ† ๋ฆฌ unique-healing๋ธ”๋กœ๊ทธ ยท ์›Œ๋“œํ”„๋ ˆ์Šค uniquehealingstory
by uniquehealing (Finance Writer)

๋” ๋งŽ์€ ์žฌํ…ŒํฌยทETF ์ฝ˜ํ…์ธ ๋Š” ๐Ÿ‘‰ [์ œ ๋ธ”๋กœ๊ทธ] ์—์„œ ํ™•์ธํ•ด ์ฃผ์„ธ์š”.

โš ๏ธ ์ €์ž‘๊ถŒ ์•ˆ๋‚ด:
๋ณธ ์ฝ˜ํ…์ธ ๋Š” ํ‹ฐ์Šคํ† ๋ฆฌ unique-healing๋ธ”๋กœ๊ทธ ๋ฐ ์›Œ๋“œํ”„๋ ˆ์Šค uniquehealingstory์˜ ์ฐฝ์ž‘๋ฌผ์ž…๋‹ˆ๋‹ค.
๐Ÿšซ ๋ฌด๋‹จ ๋ณต์ œยท๋ฐฐํฌยท์ƒ์—…์  ์ด์šฉ์„ ๊ธˆํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ“Ž ์ผ๋ถ€ ์ธ์šฉ ์‹œ์—๋Š” ๋ฐ˜๋“œ์‹œ ์ถœ์ฒ˜์™€ ์›๋ฌธ ๋งํฌ๋ฅผ ๋ช…์‹œํ•ด ์ฃผ์„ธ์š”.


uniquehealing์—์„œ ๋” ์•Œ์•„๋ณด๊ธฐ

๊ตฌ๋…์„ ์‹ ์ฒญํ•˜๋ฉด ์ตœ์‹  ๊ฒŒ์‹œ๋ฌผ์„ ์ด๋ฉ”์ผ๋กœ ๋ฐ›์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋Œ“๊ธ€ ๋‚จ๊ธฐ๊ธฐ