Add NH(나무) broker integration and fix balance/holds parsing
- finestock/nh/: Nh/NhV 브로커 클래스 추가 (시세/주문/잔고/실시간 WS)
- api_factory.py, path.py: APIProvider.NH/NHV 등록, 도메인/엔드포인트 매핑
- kis.py: get_holds/get_ohlcv_min/get_index_min/get_stock_list 스텁 추가,
oauth() Content-Type 헤더 수정
- get_balance()의 실전 디버깅으로 드러난 버그 수정:
- Hold.total(매입금액)이 존재하지 않는 byn_amt 필드를 참조해 항상 0이던 것을
eal_amt - eal_pls_amt로 계산하도록 수정
- rsp_cd를 "00000" 단일 값으로만 성공 판정해 정상 응답('00218' 연속조회 중,
'00166' 마지막 페이지 등)을 실패로 오판하던 것을 Output_0 존재 여부로 판정
- 응답 헤더의 cts/cts_flag로 연속조회를 재귀 처리해 10건 넘는 보유종목도
전부 합쳐서 반환하도록 구현
- doc/, tests/, example_*.py, setup.py, requirements.txt, CLAUDE.md 등 추가
- README.md에 .env 환경변수 설정 가이드 추가
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01225Lu4Fc2UpMz6QixEcNT8
This commit is contained in:
+157
@@ -0,0 +1,157 @@
|
||||
import os
|
||||
import sys
|
||||
import finestock
|
||||
from finestock import APIProvider
|
||||
|
||||
try:
|
||||
# 선택 의존성: 설치돼 있으면 .env 파일을 자동으로 읽어 os.environ에 채워준다.
|
||||
# pip install python-dotenv
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
#from loguru import logger
|
||||
finestock.print_version_info()
|
||||
#logging.basicConfig(level=logging.DEBUG)
|
||||
#logger.add(sys.stdout, level="DEBUG")
|
||||
|
||||
#print(logger._core.handlers) # 내부 구조 접근이지만 확인용으로는 유용
|
||||
#exit()
|
||||
|
||||
# 실키/토큰은 절대 코드에 하드코딩하지 말 것. 환경변수로 주입한다.
|
||||
# 예 (PowerShell): $env:APP_KEY="..."; $env:APP_SECRET="..."
|
||||
app_key = os.environ.get("APP_KEY", "YOUR_APP_KEY")
|
||||
app_secret = os.environ.get("APP_SECRET", "YOUR_APP_SECRET")
|
||||
account_num = os.environ.get("ACCOUNT_NUM", "YOUR_ACCOUNT_NUM")
|
||||
account_num_sub = os.environ.get("ACCOUNT_NUM_SUB", "01")
|
||||
access_token = os.environ.get("ACCESS_TOKEN", "")
|
||||
|
||||
api_type = "KISV"
|
||||
api = finestock.APIFactory.create_api(APIProvider.LS)
|
||||
|
||||
api.set_oauth_info(app_key, app_secret)
|
||||
|
||||
login = False
|
||||
if login:
|
||||
api.oauth()
|
||||
print(api.access_token)
|
||||
else:
|
||||
api.headers['authorization'] = f"Bearer {access_token}"
|
||||
|
||||
#list = api.get_condition_list("shinalok")
|
||||
#print(list)
|
||||
#list = api.get_condition_price("shinalok0000")
|
||||
#print(list)
|
||||
# etf_list = ["069500", "229200", "292190", "156080"]
|
||||
# prices = api.get_multiple_ohlcv(etf_list)
|
||||
# print(prices)
|
||||
# exit()
|
||||
#api.set_account_info(account_num, account_num_sub)
|
||||
# ohlcvs = api.get_ohlcv("233740")
|
||||
# print(ohlcvs)
|
||||
# exit()
|
||||
#ohlcvs = api.get_index_min("405", "20250514")
|
||||
ohlcvs = api.get_ohlcv_min("005930", "20250515")
|
||||
print(ohlcvs)
|
||||
print(len(ohlcvs))
|
||||
exit()
|
||||
|
||||
|
||||
acc = api.get_balance()
|
||||
print(acc)
|
||||
|
||||
#res = api.do_order("228790", finestock.ORDER_FLAG.BUY, 0, 1)
|
||||
#print(res)
|
||||
|
||||
exit()
|
||||
orderbook = api.get_orderbook("233740")
|
||||
print(orderbook)
|
||||
#ohlcvs = api.get_ohlcv("233740", "20240806", "20240806")
|
||||
ohlcvs = api.get_ohlcv("233740")
|
||||
print(ohlcvs)
|
||||
exit()
|
||||
|
||||
'''
|
||||
ohlcvs = api.get_ohlcv("005930", "20200101", "20240328")
|
||||
for price in ohlcvs:
|
||||
print(price.workday)
|
||||
exit()
|
||||
'''
|
||||
api.set_account_info(account_num, account_num_sub)
|
||||
acc = api.get_balance()
|
||||
print(acc)
|
||||
exit()
|
||||
|
||||
#ohlcvs = api.get_index("405", "20200101", "20240328")
|
||||
ohlcvs = api.get_index("405", "20240802", "20240802")
|
||||
print(ohlcvs)
|
||||
print(len(ohlcvs))
|
||||
print(ohlcvs)
|
||||
for price in ohlcvs:
|
||||
print(price.workday)
|
||||
exit()
|
||||
#Ebest만 사용 가능
|
||||
#list = api.get_index_list()
|
||||
#print(list)
|
||||
#exit()
|
||||
#res = api.do_order("004410", finestock.ORDER_FLAG.SELL, 176, 1)
|
||||
#print(res)
|
||||
#res = api.do_order_cancle("19441", "004410", 1)
|
||||
#print(res)
|
||||
res = api.get_order_status("004410")
|
||||
print(res)
|
||||
exit()
|
||||
res = api.do_order("004410", finestock.ORDER_FLAG.BUY, 170, 1)
|
||||
print(res)
|
||||
exit()
|
||||
|
||||
list = api.get_stock_list()
|
||||
print(api.stock_master)
|
||||
print(list)
|
||||
print(len(list))
|
||||
#print(list.keys())
|
||||
exit()
|
||||
|
||||
#주식 ohlcv 가져오기
|
||||
ohlcvs = api.get_ohlcv("005930", "20240101", "20240328")
|
||||
print(ohlcvs)
|
||||
logger.debug("Hihi")
|
||||
|
||||
#지수정보 가져오기
|
||||
#index = api.get_index("3003", "20240101", "20240328") #LS: 405, KIS: 3003
|
||||
#print(index)
|
||||
|
||||
#계좌정보 가져오기
|
||||
api.set_account_info(account_num, account_num_sub)
|
||||
acc = api.get_balance()
|
||||
print(acc)
|
||||
|
||||
|
||||
#주문
|
||||
#res = api.do_order("004410", finestock.ORDER_FLAG.BUY, 170, 1)
|
||||
#print(res)
|
||||
|
||||
#주문상태 확인
|
||||
res = api.get_order_status("004410")
|
||||
print(res)
|
||||
|
||||
#주문취소
|
||||
#res = api.do_order_cancle("13889", "004410", 1)
|
||||
#print(res)
|
||||
|
||||
|
||||
exit()
|
||||
#ohlcvs = api.get_ohlcv("005930", "20240101", "20240328")
|
||||
#print(ohlcvs)
|
||||
|
||||
#api.get_index_list()
|
||||
#api.get_ohlcv("005930", count=20)
|
||||
#ohlcvs = api.get_index("3003", "20240101", "20240328")
|
||||
#print(ohlcvs)
|
||||
|
||||
|
||||
#orderbook = api.get_orderbook("005930")
|
||||
#print(orderbook)
|
||||
#res = api.do_order("004410", ORDER.BUY, 150, 1)
|
||||
#res = api.do_order_cancle("12788", "004410", 1)
|
||||
Reference in New Issue
Block a user