Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b95657a49 | ||
|
|
cb5d770a1c | ||
|
|
361b560624 |
@@ -22,9 +22,6 @@ venv/
|
|||||||
# 로컬 전용 문서 (원격 저장소에는 올리지 않음)
|
# 로컬 전용 문서 (원격 저장소에는 올리지 않음)
|
||||||
doc/
|
doc/
|
||||||
|
|
||||||
# 실키/시크릿이 하드코딩된 적이 있어 정리 후 다시 올릴 예정 (원격 저장소에는 올리지 않음)
|
|
||||||
example*.py
|
|
||||||
|
|
||||||
# --- JetBrains 공식 .gitignore 파일 명세 ---
|
# --- JetBrains 공식 .gitignore 파일 명세 ---
|
||||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|||||||
+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)
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import os
|
||||||
|
import queue
|
||||||
|
import threading
|
||||||
|
|
||||||
|
from finestock import APIProvider
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 선택 의존성: 설치돼 있으면 .env 파일을 자동으로 읽어 os.environ에 채워준다.
|
||||||
|
# pip install python-dotenv
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
load_dotenv()
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
import finestock
|
||||||
|
import asyncio
|
||||||
|
from loguru import logger
|
||||||
|
import sys
|
||||||
|
logger.add(sys.stdout, level="DEBUG")
|
||||||
|
finestock.print_version_info()
|
||||||
|
|
||||||
|
data_queue = queue.Queue()
|
||||||
|
data_condition = threading.Condition()
|
||||||
|
|
||||||
|
# 실키/토큰은 절대 코드에 하드코딩하지 말 것. 환경변수로 주입한다.
|
||||||
|
# 예 (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")
|
||||||
|
access_token = os.environ.get("ACCESS_TOKEN", "")
|
||||||
|
|
||||||
|
api_type = APIProvider.LSV
|
||||||
|
api = finestock.APIFactory.create_api(api_type)
|
||||||
|
|
||||||
|
api.set_oauth_info(app_key, app_secret)
|
||||||
|
|
||||||
|
login = False
|
||||||
|
if login:
|
||||||
|
api.oauth()
|
||||||
|
print(api.access_token)
|
||||||
|
else:
|
||||||
|
api.access_token = access_token
|
||||||
|
api.headers['authorization'] = f"Bearer {access_token}"
|
||||||
|
|
||||||
|
api.set_queue(data_queue, data_condition)
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
await api.connect()
|
||||||
|
#await api.recv_orderbook("005930")
|
||||||
|
#await api.recv_price("005930")
|
||||||
|
#await api.recv_orderbook("082850")
|
||||||
|
#await api.recv_price("082850")
|
||||||
|
#await api.recv_price("233740")
|
||||||
|
|
||||||
|
#await api.recv_index("405") #코스닥 150: 405
|
||||||
|
await api.recv_order_status()
|
||||||
|
|
||||||
|
await api.run()
|
||||||
|
|
||||||
|
asyncio.run(main())
|
||||||
|
#loop = asyncio.get_event_loop()
|
||||||
|
#loop.run_until_complete(main())
|
||||||
|
#loop.close()
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
import asyncio
|
||||||
|
import queue
|
||||||
|
import sys
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
import finestock
|
||||||
|
from finestock import APIProvider
|
||||||
|
from finestock.comm.api_interface import AuthenticationProvider, RealtimeProvider
|
||||||
|
|
||||||
|
# Configure logging
|
||||||
|
logger.remove()
|
||||||
|
logger.add(sys.stdout, level="DEBUG")
|
||||||
|
|
||||||
|
async def consume_data(data_queue: queue.Queue):
|
||||||
|
"""
|
||||||
|
Background task to consume data from the queue asynchronously.
|
||||||
|
"""
|
||||||
|
logger.info("Data consumer started...")
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
if not data_queue.empty():
|
||||||
|
data = data_queue.get_nowait()
|
||||||
|
print(f"Received Realtime Data: {data}")
|
||||||
|
else:
|
||||||
|
await asyncio.sleep(0.1) # Yield control
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Consumer Error: {e}")
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
finestock.print_version_info()
|
||||||
|
|
||||||
|
# 1. Create API Instance
|
||||||
|
api = finestock.create_api(APIProvider.KIWOOM)
|
||||||
|
|
||||||
|
# 2. Setup Authentication
|
||||||
|
# Kiwoom requires app key/secret?
|
||||||
|
# Based on kiwoom.py:
|
||||||
|
# self.app_key = None
|
||||||
|
# self.app_secret = None
|
||||||
|
# OAuth uses them.
|
||||||
|
# I should use the keys if I have them or reuse from current context if needed.
|
||||||
|
# example_v1.py used:
|
||||||
|
# api.set_oauth_info("RSvh1vtzHj8Z5F15Ee7_rJ5znHuAKOF6A8v90TEkyBk", "_7wuGnkD-Crf1TJKErJPYkQp7AVuh_gVOPgQ2Uyyh7k")
|
||||||
|
|
||||||
|
auth_api: AuthenticationProvider = api
|
||||||
|
if isinstance(auth_api, AuthenticationProvider):
|
||||||
|
APP_KEY = "RSvh1vtzHj8Z5F15Ee7_rJ5znHuAKOF6A8v90TEkyBk"
|
||||||
|
APP_SECRET = "_7wuGnkD-Crf1TJKErJPYkQp7AVuh_gVOPgQ2Uyyh7k"
|
||||||
|
auth_api.set_oauth_info(APP_KEY, APP_SECRET)
|
||||||
|
token = auth_api.oauth()
|
||||||
|
logger.info(f"Logged in.")
|
||||||
|
|
||||||
|
# 3. Setup Realtime Data (Async)
|
||||||
|
realtime_api: RealtimeProvider = api
|
||||||
|
if isinstance(realtime_api, RealtimeProvider):
|
||||||
|
# Create Queue for data
|
||||||
|
data_queue = queue.Queue()
|
||||||
|
realtime_api.set_data_queue(data_queue)
|
||||||
|
|
||||||
|
# Connect to WebSocket
|
||||||
|
logger.info("Connecting to WebSocket...")
|
||||||
|
await realtime_api.connect()
|
||||||
|
|
||||||
|
# Login is handled in connect
|
||||||
|
|
||||||
|
|
||||||
|
# Subscribe to Realtime Prices
|
||||||
|
# Ex: Samsung Electronics (005930)
|
||||||
|
logger.info("Subscribing to 005930...")
|
||||||
|
await realtime_api.recv_price("005930")
|
||||||
|
|
||||||
|
# Subscribe to Realtime Index
|
||||||
|
# Ex: KOSPI (001)
|
||||||
|
logger.info("Subscribing to KOSPI (001)...")
|
||||||
|
await realtime_api.recv_index("001")
|
||||||
|
|
||||||
|
# Start the data consumer task
|
||||||
|
consumer_task = asyncio.create_task(consume_data(data_queue))
|
||||||
|
|
||||||
|
# Start the API run loop
|
||||||
|
logger.info("Starting API Event Loop...")
|
||||||
|
|
||||||
|
# Run for 10 seconds then exit for verification
|
||||||
|
try:
|
||||||
|
await asyncio.wait_for(realtime_api.run(), timeout=30)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
logger.info("Test finished (timeout)")
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
consumer_task.cancel()
|
||||||
|
await realtime_api.disconnect()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
asyncio.run(main())
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
logger.info("Terminated by user")
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
import asyncio
|
||||||
|
import os
|
||||||
|
import queue
|
||||||
|
import sys
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
import finestock
|
||||||
|
from finestock import APIProvider
|
||||||
|
from finestock.comm.api_interface import AuthenticationProvider, RealtimeProvider
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 선택 의존성: 설치돼 있으면 .env 파일을 자동으로 읽어 os.environ에 채워준다.
|
||||||
|
# pip install python-dotenv
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
load_dotenv()
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Configure logging
|
||||||
|
logger.remove()
|
||||||
|
logger.add(sys.stdout, level="DEBUG")
|
||||||
|
|
||||||
|
|
||||||
|
async def consume_data(data_queue: queue.Queue):
|
||||||
|
"""
|
||||||
|
Background task to consume data from the queue asynchronously.
|
||||||
|
"""
|
||||||
|
logger.info("Data consumer started...")
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
if not data_queue.empty():
|
||||||
|
data = data_queue.get_nowait()
|
||||||
|
print(f"Received Realtime Data: {data}")
|
||||||
|
else:
|
||||||
|
await asyncio.sleep(0.1) # Yield control
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Consumer Error: {e}")
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
finestock.print_version_info()
|
||||||
|
|
||||||
|
# 1. Create API Instance
|
||||||
|
# 모의투자로 테스트하려면 APIProvider.NHV를 사용한다. 단, 접근토큰발급(oauth())은
|
||||||
|
# NH·NHV 모두 항상 운영 도메인에서만 발급된다(모의투자 계좌로 거래하더라도 토큰은 동일).
|
||||||
|
api = finestock.create_api(APIProvider.NH)
|
||||||
|
|
||||||
|
# 2. Setup Authentication
|
||||||
|
# 실키/시크릿은 절대 코드에 하드코딩하지 말 것. 환경변수로 주입한다.
|
||||||
|
# 예 (PowerShell): $env:APP_KEY="..."; $env:APP_SECRET="..."
|
||||||
|
auth_api: AuthenticationProvider = api
|
||||||
|
if isinstance(auth_api, AuthenticationProvider):
|
||||||
|
app_key = os.environ.get("APP_KEY", "YOUR_APP_KEY")
|
||||||
|
app_secret = os.environ.get("APP_SECRET", "YOUR_APP_SECRET")
|
||||||
|
auth_api.set_oauth_info(app_key, app_secret)
|
||||||
|
auth_api.oauth()
|
||||||
|
logger.info("Logged in.")
|
||||||
|
|
||||||
|
# 3. Setup Realtime Data (Async)
|
||||||
|
realtime_api: RealtimeProvider = api
|
||||||
|
if isinstance(realtime_api, RealtimeProvider):
|
||||||
|
# Create Queue for data
|
||||||
|
data_queue = queue.Queue()
|
||||||
|
realtime_api.set_data_queue(data_queue)
|
||||||
|
|
||||||
|
# Connect to WebSocket
|
||||||
|
logger.info("Connecting to WebSocket...")
|
||||||
|
await realtime_api.connect()
|
||||||
|
|
||||||
|
# Subscribe to Realtime Price (체결가) — 삼성전자(005930)
|
||||||
|
logger.info("Subscribing to 005930 price...")
|
||||||
|
await realtime_api.recv_price("005930")
|
||||||
|
|
||||||
|
# Subscribe to Realtime Orderbook (호가) — 삼성전자(005930)
|
||||||
|
logger.info("Subscribing to 005930 orderbook...")
|
||||||
|
await realtime_api.recv_orderbook("005930")
|
||||||
|
|
||||||
|
# 참고: NH krstock API에는 지수 실시간 채널이 없어 recv_index()는 stub이다
|
||||||
|
# (호출하면 "not supported" 로그만 남기고 아무것도 구독하지 않는다).
|
||||||
|
|
||||||
|
# Start the data consumer task
|
||||||
|
consumer_task = asyncio.create_task(consume_data(data_queue))
|
||||||
|
|
||||||
|
# Start the API run loop
|
||||||
|
logger.info("Starting API Event Loop...")
|
||||||
|
|
||||||
|
# Run for 30 seconds then exit for verification
|
||||||
|
try:
|
||||||
|
await asyncio.wait_for(realtime_api.run(), timeout=30)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
logger.info("Test finished (timeout)")
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
consumer_task.cancel()
|
||||||
|
await realtime_api.disconnect()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
asyncio.run(main())
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
logger.info("Terminated by user")
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
import asyncio
|
||||||
|
import queue
|
||||||
|
import sys
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
import finestock
|
||||||
|
from finestock import APIProvider
|
||||||
|
from finestock.comm.api_interface import AuthenticationProvider, RealtimeProvider
|
||||||
|
|
||||||
|
# Configure logging
|
||||||
|
logger.remove()
|
||||||
|
logger.add(sys.stdout, level="DEBUG")
|
||||||
|
|
||||||
|
async def consume_data(data_queue: queue.Queue):
|
||||||
|
"""
|
||||||
|
Background task to consume data from the queue asynchronously.
|
||||||
|
"""
|
||||||
|
logger.info("Data consumer started...")
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
# Since refined queue is thread-safe standard queue, we can just poll it
|
||||||
|
# In a real async app, you might use asyncio.Queue for await q.get()
|
||||||
|
# But here we are injecting a standard queue as per interface.
|
||||||
|
# To avoid blocking the loop, we use run_in_executor or just poll with sleep
|
||||||
|
|
||||||
|
if not data_queue.empty():
|
||||||
|
data = data_queue.get_nowait()
|
||||||
|
# Type hinting can be used here if data structure is known
|
||||||
|
if isinstance(data, finestock.Price):
|
||||||
|
type_str = "Index" if data.code == "001" else "Price/Trade" # Simple heuristic
|
||||||
|
print(f"[{type_str}] Code: {data.code}, Time: {data.time}, Current: {data.close}, Vol: {data.volume}")
|
||||||
|
elif isinstance(data, finestock.OrderBook):
|
||||||
|
print(data)
|
||||||
|
print(f"[OrderBook] Code: {data.code}, Buy: {data.total_buy}, Sell: {data.total_sell}")
|
||||||
|
if data.buy: print(f" Best Buy: {data.buy[0].price} ({data.buy[0].qty})")
|
||||||
|
if data.sell: print(f" Best Sell: {data.sell[0].price} ({data.sell[0].qty})")
|
||||||
|
elif isinstance(data, finestock.Trade):
|
||||||
|
print(f"[Order Status] Code: {data.code}, Flag: {data.trade_flag}, Order: {data.order_flag}, Qty: {data.qty}")
|
||||||
|
else:
|
||||||
|
print(f"Received Data: {data}")
|
||||||
|
else:
|
||||||
|
await asyncio.sleep(0.1) # Yield control
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Consumer Error: {e}")
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
finestock.print_version_info()
|
||||||
|
|
||||||
|
# 0. Select Provider
|
||||||
|
# TARGET_PROVIDER = APIProvider.LSV
|
||||||
|
TARGET_PROVIDER = APIProvider.KIWOOMV
|
||||||
|
|
||||||
|
print(f"Selected Provider: {TARGET_PROVIDER.name}")
|
||||||
|
|
||||||
|
# 1. Create API Instance
|
||||||
|
api = finestock.create_api(TARGET_PROVIDER)
|
||||||
|
|
||||||
|
# 2. Setup Authentication
|
||||||
|
auth_api: AuthenticationProvider = api
|
||||||
|
if isinstance(auth_api, AuthenticationProvider):
|
||||||
|
if TARGET_PROVIDER == APIProvider.LSV:
|
||||||
|
# LSV Keys
|
||||||
|
APP_KEY = "PSgjLpp90XLhWexJYGL0P36oyzM3ne5kjhDW"
|
||||||
|
APP_SECRET = "htA3h9kULFPD75vtHAt0JaXyYAjsbf0b"
|
||||||
|
elif TARGET_PROVIDER == APIProvider.KIWOOM:
|
||||||
|
# Kiwoom Keys (Test)
|
||||||
|
APP_KEY = "RSvh1vtzHj8Z5F15Ee7_rJ5znHuAKOF6A8v90TEkyBk"
|
||||||
|
APP_SECRET = "_7wuGnkD-Crf1TJKErJPYkQp7AVuh_gVOPgQ2Uyyh7k"
|
||||||
|
elif TARGET_PROVIDER == APIProvider.KIWOOMV:
|
||||||
|
APP_KEY = "5-7V0r97uwlzmPNFa_FnwFEZtnyhFAZ1qlnDXQH2rX4"
|
||||||
|
APP_SECRET = "YOMvV7X1CwwST-_iFmRAPKXO7Wwr4zGGyTPX5gFcAqk"
|
||||||
|
|
||||||
|
auth_api.set_oauth_info(APP_KEY, APP_SECRET)
|
||||||
|
token = auth_api.oauth()
|
||||||
|
print(f"Logged in with token: {token}")
|
||||||
|
|
||||||
|
# 3. Setup Realtime Data (Async)
|
||||||
|
realtime_api: RealtimeProvider = api
|
||||||
|
if isinstance(realtime_api, RealtimeProvider):
|
||||||
|
# Create Queue for data
|
||||||
|
data_queue = queue.Queue()
|
||||||
|
realtime_api.set_data_queue(data_queue)
|
||||||
|
|
||||||
|
# Connect to WebSocket
|
||||||
|
logger.info("Connecting to WebSocket...")
|
||||||
|
await realtime_api.connect()
|
||||||
|
|
||||||
|
# Subscribe to Realtime Prices
|
||||||
|
# Subscribe to Realtime Prices, Orderbook, and Trades
|
||||||
|
# Ex: Samsung Electronics (005930)
|
||||||
|
logger.info("Subscribing to 005930 (Price, Orderbook, Trade)...")
|
||||||
|
#await realtime_api.recv_price("005930") #완료
|
||||||
|
#await realtime_api.recv_orderbook("005930") #완료
|
||||||
|
#await realtime_api.recv_trade("005930") # Same as price (0B)
|
||||||
|
|
||||||
|
logger.info("Subscribing to Order Status (00)...")
|
||||||
|
await realtime_api.recv_order_status()
|
||||||
|
|
||||||
|
# Subscribe to Index
|
||||||
|
# Ex: KOSPI (001)
|
||||||
|
logger.info("Subscribing to KOSPI Index (001)...")
|
||||||
|
#await realtime_api.recv_index("001") #완료
|
||||||
|
|
||||||
|
# Start the data consumer task
|
||||||
|
consumer_task = asyncio.create_task(consume_data(data_queue))
|
||||||
|
|
||||||
|
# Start the API run loop (This blocks until disconnected)
|
||||||
|
logger.info("Starting API Event Loop...")
|
||||||
|
|
||||||
|
await realtime_api.run()
|
||||||
|
|
||||||
|
# Cleanup (if loop breaks)
|
||||||
|
consumer_task.cancel()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
asyncio.run(main())
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
logger.info("Terminated by user")
|
||||||
+161
@@ -0,0 +1,161 @@
|
|||||||
|
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 = finestock.APIFactory.create_api(APIProvider.KIS)
|
||||||
|
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}"
|
||||||
|
|
||||||
|
res = api.get_price("329180")
|
||||||
|
print(res)
|
||||||
|
res = api.get_ohlcv("329180", "20260819", "20260820")
|
||||||
|
print(res)
|
||||||
|
exit()
|
||||||
|
#exit()
|
||||||
|
#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)
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import os
|
||||||
|
import finestock
|
||||||
|
from finestock import APIProvider
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 선택 의존성: 설치돼 있으면 .env 파일을 자동으로 읽어 os.environ에 채워준다.
|
||||||
|
# pip install python-dotenv
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
load_dotenv()
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
finestock.print_version_info()
|
||||||
|
|
||||||
|
# 실키/토큰은 절대 코드에 하드코딩하지 말 것. 환경변수로 주입한다.
|
||||||
|
# 예 (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")
|
||||||
|
access_token = os.environ.get("ACCESS_TOKEN", "")
|
||||||
|
|
||||||
|
# 모의투자로 테스트하려면 APIProvider.NHV를 사용한다. 단, 접근토큰발급(oauth())은
|
||||||
|
# NH·NHV 모두 항상 운영 도메인에서만 발급된다(모의투자 계좌로 거래하더라도 토큰은 동일).
|
||||||
|
api = finestock.APIFactory.create_api(APIProvider.NH)
|
||||||
|
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}"
|
||||||
|
|
||||||
|
# 1) 계좌 목록 조회 — /n2/acctinfo. acct_type이 01/02면 운영(NH) 전용, 03이면 모의투자(NHV) 전용.
|
||||||
|
accounts = api.get_account_list()
|
||||||
|
print(accounts)
|
||||||
|
|
||||||
|
# 계좌목록에서 사용할 계좌를 골라 세팅한다. act_no는 11자리 단일 값이라 sub는 비워둔다.
|
||||||
|
account_num = os.environ.get("ACCOUNT_NUM", "YOUR_ACCOUNT_NUM")
|
||||||
|
#account_num_sub = os.environ.get("ACCOUNT_NUM_SUB", "YOUR_ACCOUNT_NUM")
|
||||||
|
api.set_account_info(account_num, "")
|
||||||
|
|
||||||
|
'''
|
||||||
|
# 2) 시세 조회
|
||||||
|
price = api.get_price("005930")
|
||||||
|
print(price)
|
||||||
|
|
||||||
|
ohlcvs = api.get_ohlcv("005930", "20260701", "20260821")
|
||||||
|
print(len(ohlcvs), ohlcvs[:3] if ohlcvs else ohlcvs)
|
||||||
|
|
||||||
|
orderbook = api.get_orderbook("005930")
|
||||||
|
print(orderbook)
|
||||||
|
'''
|
||||||
|
# 3) 계좌/잔고 조회
|
||||||
|
acc = api.get_balance()
|
||||||
|
print(acc)
|
||||||
|
if acc:
|
||||||
|
print(len(acc.hold), acc.hold[:3] if acc.hold else acc.hold)
|
||||||
|
|
||||||
|
# 4) 주문 (실제 체결되니 운영 도메인에서는 주의 — 테스트는 APIProvider.NHV 권장)
|
||||||
|
# res = api.do_order("005930", finestock.ORDER_FLAG.BUY, 0, 1) # price=0 -> 시장가
|
||||||
|
# print(res)
|
||||||
|
# if res:
|
||||||
|
# cancel = api.do_order_cancel(res.order_num, "005930", 0) # qty<=0 -> 전량취소
|
||||||
|
# print(cancel)
|
||||||
+191
@@ -0,0 +1,191 @@
|
|||||||
|
import sys
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
import finestock
|
||||||
|
from finestock import APIProvider
|
||||||
|
from finestock.comm.api_interface import AuthenticationProvider, MarketDataProvider, TradingProvider, AccountProvider
|
||||||
|
|
||||||
|
# Configure logging
|
||||||
|
logger.remove()
|
||||||
|
logger.add(sys.stdout, level="INFO")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
finestock.print_version_info()
|
||||||
|
|
||||||
|
# 1. Create API Instance
|
||||||
|
# The 'api' object implements multiple interfaces (Authentication, MarketData, Realtime, etc.)
|
||||||
|
api = finestock.create_api(APIProvider.KIWOOMV)
|
||||||
|
|
||||||
|
# 2. Setup Authentication (Sync)
|
||||||
|
# Type Hinting: View 'api' as AuthenticationProvider to see only auth-related methods
|
||||||
|
auth_api: AuthenticationProvider = api
|
||||||
|
if isinstance(auth_api, AuthenticationProvider):
|
||||||
|
#APP_KEY = "YOUR_APP_KEY"
|
||||||
|
#APP_SECRET = "YOUR_APP_SECRET"
|
||||||
|
#APP_KEY = "PSgjLpp90XLhWexJYGL0P36oyzM3ne5kjhDW" #LSV
|
||||||
|
#APP_SECRET = "htA3h9kULFPD75vtHAt0JaXyYAjsbf0b" #LSV
|
||||||
|
#APP_KEY = "RSvh1vtzHj8Z5F15Ee7_rJ5znHuAKOF6A8v90TEkyBk"
|
||||||
|
#APP_SECRET = "_7wuGnkD-Crf1TJKErJPYkQp7AVuh_gVOPgQ2Uyyh7k"
|
||||||
|
APP_KEY = "5-7V0r97uwlzmPNFa_FnwFEZtnyhFAZ1qlnDXQH2rX4"
|
||||||
|
APP_SECRET = "YOMvV7X1CwwST-_iFmRAPKXO7Wwr4zGGyTPX5gFcAqk"
|
||||||
|
auth_api.set_oauth_info(APP_KEY, APP_SECRET)
|
||||||
|
token = auth_api.oauth()
|
||||||
|
print(token)
|
||||||
|
# auth_api.oauth() # Perform actual login
|
||||||
|
# or auth_api.set_access_token("TOKEN")
|
||||||
|
|
||||||
|
# 3. Market Data (Sync)
|
||||||
|
logger.info("Fetching Market Data (Sync)...")
|
||||||
|
# Type Hinting: View 'api' as MarketDataProvider
|
||||||
|
market_api: MarketDataProvider = api
|
||||||
|
if isinstance(market_api, MarketDataProvider):
|
||||||
|
try:
|
||||||
|
# ohlcvs = market_api.get_ohlcv("005930", "20240101", "20240105")
|
||||||
|
# print(f"Received {len(ohlcvs)} records")
|
||||||
|
ohlcv = market_api.get_price("005930")
|
||||||
|
print(f"Received {ohlcv}")
|
||||||
|
exit()
|
||||||
|
|
||||||
|
# Example: Parsing Price objects
|
||||||
|
print(f"{'Date':<10} | {'Close':<10} | {'Volume':<10}")
|
||||||
|
print("-" * 36)
|
||||||
|
|
||||||
|
price: finestock.Price = ohlcv
|
||||||
|
# Accessing fields of the Price dataclass
|
||||||
|
print(f"{price.workday:<10} | {price.close:<10} | {price.volume:<10}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Market Data Error: {e}")
|
||||||
|
exit()
|
||||||
|
try:
|
||||||
|
# ohlcvs = market_api.get_ohlcv("005930", "20240101", "20240105")
|
||||||
|
# print(f"Received {len(ohlcvs)} records")
|
||||||
|
ohlcvs = market_api.get_ohlcv("005930", "20240101", "20240105")
|
||||||
|
print(f"Received {len(ohlcvs)} records")
|
||||||
|
|
||||||
|
# Example: Parsing Price objects
|
||||||
|
print(f"{'Date':<10} | {'Close':<10} | {'Volume':<10}")
|
||||||
|
print("-" * 36)
|
||||||
|
for price in ohlcvs:
|
||||||
|
price: finestock.Price = price
|
||||||
|
# Accessing fields of the Price dataclass
|
||||||
|
print(f"{price.workday:<10} | {price.close:<10} | {price.volume:<10}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Market Data Error: {e}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
logger.info("Fetching Stock List (KOSPI)...")
|
||||||
|
# info_api = api # InfoProvider
|
||||||
|
if hasattr(market_api, 'get_stock_list'):
|
||||||
|
stocks = market_api.get_stock_list("0") # 0: KOSPI
|
||||||
|
print(f"Received {len(stocks)} stocks for KOSPI")
|
||||||
|
print(f"First 5 stocks:")
|
||||||
|
for s in stocks[:5]:
|
||||||
|
print(s)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Stock List Error: {e}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
logger.info("Fetching KOSDAQ Index List...")
|
||||||
|
# market_api is typed as MarketDataProvider if using interface, but get_index_list is specific to Kiwoom or extended interface
|
||||||
|
# Since market_api is actually the API instance, we can call it if available
|
||||||
|
if hasattr(market_api, 'get_index_list'):
|
||||||
|
indices = market_api.get_index_list("0") # 0: KOSPI
|
||||||
|
print(f"Received {len(indices)} indices for KOSPI")
|
||||||
|
print(f"First 5 indices:")
|
||||||
|
for idx in indices[:5]:
|
||||||
|
print(f"Code: {idx.code}, Name: {idx.name}, Market: {idx.market}, Group: {idx.group}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Index List Error: {e}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
logger.info("Fetching KOSDAQ 150 Index Data...")
|
||||||
|
# KOSDAQ 150 Code: 150
|
||||||
|
ohlcvs = market_api.get_index("150", "20260201", "20260213")
|
||||||
|
print(f"Received {len(ohlcvs)} records for KOSDAQ 150")
|
||||||
|
|
||||||
|
print(f"{'Date':<10} | {'Close':<10} | {'Volume':<10}")
|
||||||
|
print("-" * 36)
|
||||||
|
for price in ohlcvs:
|
||||||
|
price: finestock.Price = price
|
||||||
|
print(f"{price.workday:<10} | {price.close:<10} | {price.volume:<10}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"KOSDAQ 150 Error: {e}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
logger.info("Fetching Orderbook for Samsung Electronics (005930)...")
|
||||||
|
orderbook = market_api.get_orderbook("005930")
|
||||||
|
if orderbook:
|
||||||
|
print(f"Orderbook for {orderbook.code}")
|
||||||
|
print(f"Total Buy: {orderbook.total_buy}, Total Sell: {orderbook.total_sell}")
|
||||||
|
print("Sell Side (Top 5):")
|
||||||
|
for h in orderbook.sell[:5]:
|
||||||
|
print(f" Price: {h.price}, Qty: {h.qty}")
|
||||||
|
print("Buy Side (Top 5):")
|
||||||
|
for h in orderbook.buy[:5]:
|
||||||
|
print(f" Price: {h.price}, Qty: {h.qty}")
|
||||||
|
else:
|
||||||
|
print("Orderbook empty or failed.")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Orderbook Error: {e}")
|
||||||
|
|
||||||
|
# 4. Trading (Sync)
|
||||||
|
logger.info("Trading Example...")
|
||||||
|
trading_api: TradingProvider = api
|
||||||
|
if isinstance(trading_api, TradingProvider):
|
||||||
|
try:
|
||||||
|
# Example: Buy Samsung Electronics (005930) 1 share at Market Price
|
||||||
|
# trde_tp 3: Market Price, 0: Limit Price
|
||||||
|
# In do_order, price=0 means Market Price (trde_tp="3")
|
||||||
|
|
||||||
|
# Uncomment to execute
|
||||||
|
# logger.info("Placing Buy Order for 005930 (1 qty, Market Price)...")
|
||||||
|
#result = trading_api.do_order("005930", finestock.ORDER_FLAG.BUY, 0, 1)
|
||||||
|
#result = trading_api.do_order("005930", finestock.ORDER_FLAG.BUY, 173000, 1)
|
||||||
|
#result = trading_api.do_order("005930", finestock.ORDER_FLAG.BUY, 176000, 1)
|
||||||
|
result = trading_api.do_order_cancel("0157069", "005930", 1)
|
||||||
|
#result = trading_api.do_order("005930", finestock.ORDER_FLAG.SELL, 177200, 1)
|
||||||
|
print(f"Order Result: {result}")
|
||||||
|
|
||||||
|
#print("To place an order, uncomment the lines in the script.")
|
||||||
|
|
||||||
|
# Example: Cancel Order
|
||||||
|
# logger.info("Cancelling Order 0000140 for 005930 (1 qty)...")
|
||||||
|
# result = trading_api.do_order_cancel("0000140", "005930", 1)
|
||||||
|
# print(f"Cancel Result: {result}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Trading Error: {e}")
|
||||||
|
|
||||||
|
# 5. Account (Sync)
|
||||||
|
logger.info("Account Example...")
|
||||||
|
account_api: AccountProvider = api
|
||||||
|
if isinstance(account_api, AccountProvider):
|
||||||
|
try:
|
||||||
|
logger.info("Fetching Account Balance...")
|
||||||
|
balance = account_api.get_balance()
|
||||||
|
if balance:
|
||||||
|
print(f"Account: {balance.account_num}")
|
||||||
|
print(f"Deposit: {balance.deposit}")
|
||||||
|
print(f"Next Deposit: {balance.next_deposit}")
|
||||||
|
print(f"Pay Deposit: {balance.pay_deposit}")
|
||||||
|
else:
|
||||||
|
print("Failed to get balance.")
|
||||||
|
|
||||||
|
logger.info("Fetching Account Holdings...")
|
||||||
|
holds = account_api.get_holds()
|
||||||
|
print(f"Received {len(holds)} holdings")
|
||||||
|
if holds:
|
||||||
|
print(f"{'Code':<10} | {'Name':<20} | {'Qty':<10} | {'Eval':<15}")
|
||||||
|
print("-" * 60)
|
||||||
|
for h in holds:
|
||||||
|
print(f"{h.code:<10} | {h.name:<20} | {h.qty:<10} | {h.eval:<15}")
|
||||||
|
else:
|
||||||
|
print("No holdings or failed to fetch.")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Account Error: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user