kispilot 0.1.2__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. kispilot-0.2.0/PKG-INFO +98 -0
  2. kispilot-0.2.0/README.md +63 -0
  3. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/__init__.py +1 -1
  4. kispilot-0.2.0/src/kispilot/api/data/_mst.py +44 -0
  5. kispilot-0.2.0/src/kispilot/api/data/index_fo.py +22 -0
  6. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/data/master.py +10 -5
  7. kispilot-0.2.0/src/kispilot/api/data/night_future.py +33 -0
  8. kispilot-0.2.0/src/kispilot/api/data/night_option.py +33 -0
  9. kispilot-0.2.0/src/kispilot/api/futureoption/__init__.py +19 -0
  10. kispilot-0.2.0/src/kispilot/api/futureoption/futureoption_inquire_asking_price.py +142 -0
  11. kispilot-0.2.0/src/kispilot/api/futureoption/futureoption_inquire_daily_fuopchartprice.py +148 -0
  12. kispilot-0.2.0/src/kispilot/api/futureoption/futureoption_inquire_price.py +155 -0
  13. kispilot-0.2.0/src/kispilot/api/futureoption/futureoption_inquire_time_fuopchartprice.py +154 -0
  14. kispilot-0.2.0/src/kispilot/api/realtime/__init__.py +21 -0
  15. kispilot-0.2.0/src/kispilot/api/realtime/realtime_index_futures_asking_price.py +199 -0
  16. kispilot-0.2.0/src/kispilot/api/realtime/realtime_index_futures_ccnl.py +209 -0
  17. kispilot-0.2.0/src/kispilot/api/realtime/realtime_index_option_asking_price.py +199 -0
  18. kispilot-0.2.0/src/kispilot/api/realtime/realtime_index_option_ccnl.py +217 -0
  19. kispilot-0.2.0/src/kispilot/api/realtime/realtime_krx_ngt_futures_asking_price.py +199 -0
  20. kispilot-0.2.0/src/kispilot/api/realtime/realtime_krx_ngt_futures_ccnl.py +208 -0
  21. kispilot-0.2.0/src/kispilot/api/realtime/realtime_krx_ngt_option_asking_price.py +199 -0
  22. kispilot-0.2.0/src/kispilot/api/realtime/realtime_krx_ngt_option_ccnl.py +215 -0
  23. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/main.py +85 -6
  24. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/assets/css/base.css +7 -0
  25. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/assets/js/api.js +4 -3
  26. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/assets/js/chart.js +5 -4
  27. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/assets/js/layout.js +1 -0
  28. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/assets/js/live.js +3 -2
  29. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/assets/js/pages/backtest.js +358 -4
  30. kispilot-0.2.0/src/kispilot/app/ui/assets/js/pages/fo.js +412 -0
  31. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/assets/js/ui.js +4 -4
  32. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/backtest.html +91 -7
  33. kispilot-0.2.0/src/kispilot/app/ui/fo.html +110 -0
  34. kispilot-0.2.0/src/kispilot/app/utils/backtest.py +585 -0
  35. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/utils/chart.py +93 -2
  36. kispilot-0.2.0/src/kispilot/app/utils/fo_board.py +320 -0
  37. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/utils/realtime_hub.py +23 -2
  38. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/mcp_server/analysis_tools.py +177 -1
  39. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/mcp_server/prompts.py +2 -1
  40. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/mcp_server/server.py +26 -1
  41. kispilot-0.2.0/src/kispilot.egg-info/PKG-INFO +98 -0
  42. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot.egg-info/SOURCES.txt +19 -0
  43. kispilot-0.1.2/PKG-INFO +0 -262
  44. kispilot-0.1.2/README.md +0 -227
  45. kispilot-0.1.2/src/kispilot/api/data/_mst.py +0 -20
  46. kispilot-0.1.2/src/kispilot/api/realtime/__init__.py +0 -9
  47. kispilot-0.1.2/src/kispilot/app/utils/backtest.py +0 -347
  48. kispilot-0.1.2/src/kispilot.egg-info/PKG-INFO +0 -262
  49. {kispilot-0.1.2 → kispilot-0.2.0}/LICENSE +0 -0
  50. {kispilot-0.1.2 → kispilot-0.2.0}/pyproject.toml +0 -0
  51. {kispilot-0.1.2 → kispilot-0.2.0}/setup.cfg +0 -0
  52. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/__main__.py +0 -0
  53. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/__init__.py +0 -0
  54. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/account/__init__.py +0 -0
  55. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/account/account_asset_balance.py +0 -0
  56. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/account/account_inquire_balance_rlz_pl.py +0 -0
  57. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/account/account_inquire_period_profit.py +0 -0
  58. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/account/account_inquire_period_rights.py +0 -0
  59. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/account/account_inquire_period_trade_profit.py +0 -0
  60. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/account/account_intgr_margin.py +0 -0
  61. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/config.py +0 -0
  62. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/data/__init__.py +0 -0
  63. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/data/kosdaq.py +0 -0
  64. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/data/kospi.py +0 -0
  65. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/data/sector.py +0 -0
  66. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/info/__init__.py +0 -0
  67. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/info/info_balance_sheet.py +0 -0
  68. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/info/info_financial_ratio.py +0 -0
  69. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/info/info_growth_ratio.py +0 -0
  70. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/info/info_income_statement.py +0 -0
  71. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/info/info_other_major_ratios.py +0 -0
  72. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/info/info_profit_ratio.py +0 -0
  73. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/info/info_search_stock_info.py +0 -0
  74. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/info/info_stability_ratio.py +0 -0
  75. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/oauth/__init__.py +0 -0
  76. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/oauth/kis_token.py +0 -0
  77. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/order/__init__.py +0 -0
  78. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/order/order_cash.py +0 -0
  79. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/order/order_credit.py +0 -0
  80. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/order/order_inquire_balance.py +0 -0
  81. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/order/order_inquire_credit_psamount.py +0 -0
  82. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/order/order_inquire_daily_ccld.py +0 -0
  83. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/order/order_inquire_psbl_order.py +0 -0
  84. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/order/order_inquire_psbl_sell.py +0 -0
  85. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/order/order_inquire_reserve.py +0 -0
  86. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/order/order_inquire_revise_cancel.py +0 -0
  87. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/order/order_reserve.py +0 -0
  88. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/order/order_reserve_revise_cancel.py +0 -0
  89. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/order/order_revise_cancel.py +0 -0
  90. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price/__init__.py +0 -0
  91. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price/price_inquire_asking_price.py +0 -0
  92. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price/price_inquire_ccnl.py +0 -0
  93. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price/price_inquire_daily_itemchartprice.py +0 -0
  94. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price/price_inquire_daily_price.py +0 -0
  95. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price/price_inquire_etf_component_stock_price.py +0 -0
  96. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price/price_inquire_etf_price.py +0 -0
  97. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price/price_inquire_investor.py +0 -0
  98. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price/price_inquire_member.py +0 -0
  99. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price/price_inquire_price.py +0 -0
  100. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price/price_inquire_time_dailychartprice.py +0 -0
  101. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price/price_inquire_time_itemchartprice.py +0 -0
  102. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price/price_inquire_time_itemconclusion.py +0 -0
  103. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price/price_nav_comparison_daily_trend.py +0 -0
  104. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price/price_nav_comparison_time_trend.py +0 -0
  105. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price/price_nav_comparison_trend.py +0 -0
  106. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price_anal/__init__.py +0 -0
  107. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price_anal/price_anal_daily_loan_trans.py +0 -0
  108. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price_anal/price_anal_daily_short_sale.py +0 -0
  109. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price_anal/price_anal_foreign_institution_total.py +0 -0
  110. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price_anal/price_anal_frgnmem_pchs_trend.py +0 -0
  111. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price_anal/price_anal_inquire_investor_daily_by_market.py +0 -0
  112. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price_anal/price_anal_intstock_multprice.py +0 -0
  113. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price_anal/price_anal_investor_program_trade_today.py +0 -0
  114. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price_anal/price_anal_investor_trade_by_stock_daily.py +0 -0
  115. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price_anal/price_anal_mktfunds.py +0 -0
  116. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price_anal/price_anal_pbar_tratio.py +0 -0
  117. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price_anal/price_anal_program_trade_by_stock.py +0 -0
  118. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/price_anal/price_anal_program_trade_by_stock_daily.py +0 -0
  119. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/ranking_anal/__init__.py +0 -0
  120. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/ranking_anal/ranking_anal_credit_balance.py +0 -0
  121. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/ranking_anal/ranking_anal_disparity.py +0 -0
  122. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/ranking_anal/ranking_anal_exp_trans_updown.py +0 -0
  123. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/ranking_anal/ranking_anal_finance_ratio.py +0 -0
  124. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/ranking_anal/ranking_anal_fluctuation.py +0 -0
  125. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/ranking_anal/ranking_anal_market_cap.py +0 -0
  126. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/ranking_anal/ranking_anal_market_value.py +0 -0
  127. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/ranking_anal/ranking_anal_prefer_disparate_ratio.py +0 -0
  128. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/ranking_anal/ranking_anal_profit_asset_index.py +0 -0
  129. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/ranking_anal/ranking_anal_quote_balance.py +0 -0
  130. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/ranking_anal/ranking_anal_short_sale.py +0 -0
  131. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/ranking_anal/ranking_anal_volume_power.py +0 -0
  132. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/ranking_anal/ranking_anal_volume_rank.py +0 -0
  133. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/realtime/realtime_asking_price_total.py +0 -0
  134. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/realtime/realtime_ccnl_total.py +0 -0
  135. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/realtime/realtime_member_total.py +0 -0
  136. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/realtime/realtime_program_trade_total.py +0 -0
  137. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/sector/__init__.py +0 -0
  138. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/sector/sector_exp_index_trend.py +0 -0
  139. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/sector/sector_exp_total_index.py +0 -0
  140. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/sector/sector_inquire_daily_indexchartprice.py +0 -0
  141. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/sector/sector_inquire_index_category_price.py +0 -0
  142. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/sector/sector_inquire_index_daily_price.py +0 -0
  143. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/sector/sector_inquire_index_price.py +0 -0
  144. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/sector/sector_inquire_index_timeprice.py +0 -0
  145. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/sector/sector_news_title.py +0 -0
  146. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/utils/__init__.py +0 -0
  147. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/utils/api_tracker.py +0 -0
  148. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/api/utils/http_session.py +0 -0
  149. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/__init__.py +0 -0
  150. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/backtest/__init__.py +0 -0
  151. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/backtest/custom_strategy.py +0 -0
  152. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/backtest/engine.py +0 -0
  153. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/backtest/indicators_lib.py +0 -0
  154. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/backtest/metrics.py +0 -0
  155. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/backtest/strategies.py +0 -0
  156. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/account.html +0 -0
  157. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/assets/favicon.svg +0 -0
  158. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/assets/js/chart-tools.js +0 -0
  159. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/assets/js/indicators.js +0 -0
  160. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/assets/js/pages/account.js +0 -0
  161. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/assets/js/pages/dashboard.js +0 -0
  162. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/assets/js/pages/etf.js +0 -0
  163. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/assets/js/pages/market.js +0 -0
  164. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/assets/js/pages/ranking.js +0 -0
  165. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/assets/js/pages/stock-finance.js +0 -0
  166. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/assets/js/pages/stock-flow.js +0 -0
  167. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/assets/js/pages/stock.js +0 -0
  168. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/assets/js/pages/trade.js +0 -0
  169. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/etf.html +0 -0
  170. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/index.html +0 -0
  171. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/market.html +0 -0
  172. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/ranking.html +0 -0
  173. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/stock-finance.html +0 -0
  174. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/stock-flow.html +0 -0
  175. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/stock.html +0 -0
  176. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/ui/trade.html +0 -0
  177. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/utils/__init__.py +0 -0
  178. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/utils/news.py +0 -0
  179. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/app/utils/utils.py +0 -0
  180. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/cli.py +0 -0
  181. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/credentials.py +0 -0
  182. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/install.py +0 -0
  183. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/mcp_server/__init__.py +0 -0
  184. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/mcp_server/shaping.py +0 -0
  185. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot/paths.py +0 -0
  186. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot.egg-info/dependency_links.txt +0 -0
  187. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot.egg-info/entry_points.txt +0 -0
  188. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot.egg-info/requires.txt +0 -0
  189. {kispilot-0.1.2 → kispilot-0.2.0}/src/kispilot.egg-info/top_level.txt +0 -0
@@ -0,0 +1,98 @@
1
+ Metadata-Version: 2.4
2
+ Name: kispilot
3
+ Version: 0.2.0
4
+ Summary: 한국투자증권 Open API를 AI 에이전트(MCP)와 웹 콘솔에서 쓰기 위한 도구 모음 (비공식)
5
+ Author: Dong-Ju An
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/dongju923/kispilot
8
+ Project-URL: Repository, https://github.com/dongju923/kispilot
9
+ Project-URL: Issues, https://github.com/dongju923/kispilot/issues
10
+ Project-URL: Changelog, https://github.com/dongju923/kispilot/releases
11
+ Keywords: kis,korea-investment,한국투자증권,mcp,trading,backtest,claude,agent
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Natural Language :: Korean
18
+ Classifier: Topic :: Office/Business :: Financial :: Investment
19
+ Requires-Python: >=3.11
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: requests>=2.31
23
+ Requires-Dist: python-dotenv>=1.0
24
+ Requires-Dist: keyring>=25
25
+ Requires-Dist: platformdirs>=4
26
+ Requires-Dist: pandas>=2.2
27
+ Requires-Dist: numpy>=1.26
28
+ Requires-Dist: yfinance>=0.2.40
29
+ Requires-Dist: starlette>=0.37
30
+ Requires-Dist: uvicorn>=0.30
31
+ Requires-Dist: websockets>=12
32
+ Requires-Dist: aiohttp>=3.9
33
+ Requires-Dist: mcp<3,>=2.2
34
+ Dynamic: license-file
35
+
36
+ # KISPilot
37
+
38
+ 한국투자증권 Open API를 **AI 에이전트(MCP)** 와 **웹 콘솔**에서 쓰기 위한 도구 모음입니다.
39
+
40
+ > **비공식 프로젝트입니다.** 한국투자증권과 관계가 없으며, 한국투자증권이 만들거나 검증하지 않았습니다.
41
+ > 이 소프트웨어는 투자 조언이 아니며, 주문·백테스트 결과로 생긴 손실에 대해 책임지지 않습니다 (MIT 라이선스, 무보증).
42
+ > 실전 계좌로 쓰기 전에 모의투자로 충분히 확인하세요.
43
+
44
+ ## 할 수 있는 것
45
+
46
+ - **조회** — 시세·호가·체결, 투자자·수급, 재무, 순위, 업종·지수, ETF, 계좌 잔고·손익 (KIS API 80여 개)
47
+ - **선물·옵션** — KOSPI200 선물·옵션(미니·위클리 포함) 주간·야간 전광판, 실시간 호가·체결, 차트
48
+ - **주문** — 현금·신용·예약 주문, 정정·취소 (에이전트는 모의투자가 기본, 실전은 2단계 확인)
49
+ - **차트** — 1분~년봉, 이동평균·볼린저·일목균형표 등 지표, 보조 차트 30여 종
50
+ - **백테스트** — 기본 전략 11종 + 지표 157개로 만드는 커스텀 전략, 여러 전략 비교, 여러 종목 포트폴리오
51
+ - **실시간** — KIS 웹소켓 체결·호가 (웹 콘솔)
52
+
53
+ ## 빠른 시작
54
+
55
+ Python 3.11 이상이 필요합니다.
56
+
57
+ **1. 설치**
58
+
59
+ ```bash
60
+ uv tool install kispilot # 또는: pipx install kispilot / pip install kispilot
61
+ ```
62
+
63
+ **2. 키 등록 (처음 한 번)** — [KIS Developers](https://apiportal.koreainvestment.com)에서 앱키·앱시크릿을 발급받은 뒤:
64
+
65
+ ```bash
66
+ kispilot setup # 실전 / 모의투자 / 둘 다 선택 → 앱키·시크릿·계좌 입력
67
+ ```
68
+
69
+ 앱키는 OS 키체인에 저장됩니다. **키를 AI 채팅창에 붙여넣지 마세요.**
70
+
71
+ **3. 쓰는 방법 고르기**
72
+
73
+ | 이렇게 쓰려면 | 실행 |
74
+ |---|---|
75
+ | 웹 화면에서 직접 보기 | `kispilot ui` → http://127.0.0.1:8000 |
76
+ | Claude 등 AI 에이전트에게 맡기기 | `kispilot install claude-desktop` (Claude Code · Cursor · VS Code · Gemini CLI · Codex 도 지원) 후 앱 다시 시작 |
77
+
78
+ ## 안내 문서
79
+
80
+ | 문서 | 이럴 때 보세요 |
81
+ |---|---|
82
+ | [설치 · 키 등록](https://github.com/dongju923/kispilot/blob/main/docs/install.md) | 업데이트·삭제, 소스 설치, 서버처럼 키체인이 없는 환경, 데이터 저장 위치 |
83
+ | [웹 콘솔](https://github.com/dongju923/kispilot/blob/main/docs/web-console.md) | 화면마다 무엇을 볼 수 있는지, 다른 기기에서 접속하기 |
84
+ | [선물 · 옵션](https://github.com/dongju923/kispilot/blob/main/docs/futures-options.md) | KOSPI200 선물·옵션 전광판, 주간/야간, 알아 둘 점 |
85
+ | [AI 에이전트 (MCP)](https://github.com/dongju923/kispilot/blob/main/docs/mcp.md) | 클라이언트별 등록, 도구·프롬프트 목록, 직접 설정, 주문 안전장치 |
86
+
87
+ 버전별 변경 내용은 [Releases](https://github.com/dongju923/kispilot/releases) 에 있습니다.
88
+
89
+ ## 데이터 출처 · 참고
90
+
91
+ - [한국투자증권 Open API](https://apiportal.koreainvestment.com) — 모든 시세·계좌·주문 기능은 이 API 를 호출합니다.
92
+ - [yfinance](https://github.com/ranaroussi/yfinance) — 주식 과거 일봉·분봉 (Yahoo Finance, 개인적·연구 목적 이용 권장). 최근 거래일은 KIS API로 보강
93
+ - [TradingView Lightweight Charts](https://github.com/tradingview/lightweight-charts) — 차트 (Apache-2.0)
94
+ - [koreainvestment/open-trading-api](https://github.com/koreainvestment/open-trading-api) — 백테스트 기본 전략 구성(프리셋 종류)과 종목 마스터 파일 형식(필드 폭·열 이름)을 참고했습니다.
95
+
96
+ ## 라이선스
97
+
98
+ [MIT](https://github.com/dongju923/kispilot/blob/main/LICENSE)
@@ -0,0 +1,63 @@
1
+ # KISPilot
2
+
3
+ 한국투자증권 Open API를 **AI 에이전트(MCP)** 와 **웹 콘솔**에서 쓰기 위한 도구 모음입니다.
4
+
5
+ > **비공식 프로젝트입니다.** 한국투자증권과 관계가 없으며, 한국투자증권이 만들거나 검증하지 않았습니다.
6
+ > 이 소프트웨어는 투자 조언이 아니며, 주문·백테스트 결과로 생긴 손실에 대해 책임지지 않습니다 (MIT 라이선스, 무보증).
7
+ > 실전 계좌로 쓰기 전에 모의투자로 충분히 확인하세요.
8
+
9
+ ## 할 수 있는 것
10
+
11
+ - **조회** — 시세·호가·체결, 투자자·수급, 재무, 순위, 업종·지수, ETF, 계좌 잔고·손익 (KIS API 80여 개)
12
+ - **선물·옵션** — KOSPI200 선물·옵션(미니·위클리 포함) 주간·야간 전광판, 실시간 호가·체결, 차트
13
+ - **주문** — 현금·신용·예약 주문, 정정·취소 (에이전트는 모의투자가 기본, 실전은 2단계 확인)
14
+ - **차트** — 1분~년봉, 이동평균·볼린저·일목균형표 등 지표, 보조 차트 30여 종
15
+ - **백테스트** — 기본 전략 11종 + 지표 157개로 만드는 커스텀 전략, 여러 전략 비교, 여러 종목 포트폴리오
16
+ - **실시간** — KIS 웹소켓 체결·호가 (웹 콘솔)
17
+
18
+ ## 빠른 시작
19
+
20
+ Python 3.11 이상이 필요합니다.
21
+
22
+ **1. 설치**
23
+
24
+ ```bash
25
+ uv tool install kispilot # 또는: pipx install kispilot / pip install kispilot
26
+ ```
27
+
28
+ **2. 키 등록 (처음 한 번)** — [KIS Developers](https://apiportal.koreainvestment.com)에서 앱키·앱시크릿을 발급받은 뒤:
29
+
30
+ ```bash
31
+ kispilot setup # 실전 / 모의투자 / 둘 다 선택 → 앱키·시크릿·계좌 입력
32
+ ```
33
+
34
+ 앱키는 OS 키체인에 저장됩니다. **키를 AI 채팅창에 붙여넣지 마세요.**
35
+
36
+ **3. 쓰는 방법 고르기**
37
+
38
+ | 이렇게 쓰려면 | 실행 |
39
+ |---|---|
40
+ | 웹 화면에서 직접 보기 | `kispilot ui` → http://127.0.0.1:8000 |
41
+ | Claude 등 AI 에이전트에게 맡기기 | `kispilot install claude-desktop` (Claude Code · Cursor · VS Code · Gemini CLI · Codex 도 지원) 후 앱 다시 시작 |
42
+
43
+ ## 안내 문서
44
+
45
+ | 문서 | 이럴 때 보세요 |
46
+ |---|---|
47
+ | [설치 · 키 등록](https://github.com/dongju923/kispilot/blob/main/docs/install.md) | 업데이트·삭제, 소스 설치, 서버처럼 키체인이 없는 환경, 데이터 저장 위치 |
48
+ | [웹 콘솔](https://github.com/dongju923/kispilot/blob/main/docs/web-console.md) | 화면마다 무엇을 볼 수 있는지, 다른 기기에서 접속하기 |
49
+ | [선물 · 옵션](https://github.com/dongju923/kispilot/blob/main/docs/futures-options.md) | KOSPI200 선물·옵션 전광판, 주간/야간, 알아 둘 점 |
50
+ | [AI 에이전트 (MCP)](https://github.com/dongju923/kispilot/blob/main/docs/mcp.md) | 클라이언트별 등록, 도구·프롬프트 목록, 직접 설정, 주문 안전장치 |
51
+
52
+ 버전별 변경 내용은 [Releases](https://github.com/dongju923/kispilot/releases) 에 있습니다.
53
+
54
+ ## 데이터 출처 · 참고
55
+
56
+ - [한국투자증권 Open API](https://apiportal.koreainvestment.com) — 모든 시세·계좌·주문 기능은 이 API 를 호출합니다.
57
+ - [yfinance](https://github.com/ranaroussi/yfinance) — 주식 과거 일봉·분봉 (Yahoo Finance, 개인적·연구 목적 이용 권장). 최근 거래일은 KIS API로 보강
58
+ - [TradingView Lightweight Charts](https://github.com/tradingview/lightweight-charts) — 차트 (Apache-2.0)
59
+ - [koreainvestment/open-trading-api](https://github.com/koreainvestment/open-trading-api) — 백테스트 기본 전략 구성(프리셋 종류)과 종목 마스터 파일 형식(필드 폭·열 이름)을 참고했습니다.
60
+
61
+ ## 라이선스
62
+
63
+ [MIT](https://github.com/dongju923/kispilot/blob/main/LICENSE)
@@ -1,3 +1,3 @@
1
1
  """KISPilot — 한국투자증권 Open API 를 AI 에이전트(MCP)와 웹 콘솔에서 쓰기 위한 도구 모음 (비공식)."""
2
2
 
3
- __version__ = "0.1.2"
3
+ __version__ = "0.2.0"
@@ -0,0 +1,44 @@
1
+ """마스터(.mst) 고정 폭 파일 파싱 공통부 — 종목 마스터는 앞부분(코드·이름) + 뒤쪽 고정 폭 필드로 이뤄진다."""
2
+ from __future__ import annotations
3
+
4
+ import csv
5
+ import io
6
+ from pathlib import Path
7
+ from typing import Optional
8
+
9
+ import pandas as pd
10
+
11
+
12
+ def parse_stock_mst(path: Path, tail_len: int, name_col: str, widths: list[int], columns: list[str]) -> pd.DataFrame:
13
+ """한 줄 = [단축코드 9][표준코드 12][한글명 …][고정 폭 필드 tail_len] (cp949)."""
14
+ head, tail = [], []
15
+ with open(path, encoding="cp949") as f:
16
+ for row in f:
17
+ front = row[: len(row) - tail_len]
18
+ head.append((front[0:9].rstrip(), front[9:21].rstrip(), front[21:].strip()))
19
+ tail.append(row[-tail_len:])
20
+ df1 = pd.DataFrame(head, columns=["단축코드", "표준코드", name_col])
21
+ df2 = pd.read_fwf(io.StringIO("".join(tail)), widths=widths, names=columns)
22
+ return pd.merge(df1, df2, how="outer", left_index=True, right_index=True)
23
+
24
+
25
+ def parse_fixed_bytes_mst(path: Path, fields: list[tuple[str, int, Optional[int]]]) -> pd.DataFrame:
26
+ """필드 위치가 cp949 바이트 기준으로 고정된 마스터. fields = [(열 이름, 시작, 끝)], 끝이 None 이면 줄 끝까지.
27
+
28
+ 한글이 2바이트라 문자열로 디코딩한 뒤 문자 위치로 자르면 한글 이름이 있는 줄마다 뒤 필드가 밀린다.
29
+ 그래서 줄을 바이트로 읽어 자른 뒤 필드마다 디코딩한다.
30
+ """
31
+ rows = []
32
+ with open(path, "rb") as f:
33
+ for line in f:
34
+ line = line.rstrip(b"\r\n")
35
+ if line.strip():
36
+ rows.append([line[a:b].decode("cp949").strip() for _, a, b in fields])
37
+ return pd.DataFrame(rows, columns=[name for name, _, _ in fields])
38
+
39
+
40
+ def parse_pipe_mst(path: Path, columns: list[str]) -> pd.DataFrame:
41
+ """'|' 로 나뉜 마스터. 코드 앞자리 0 이 사라지지 않게 모든 값을 문자열로 읽는다."""
42
+ df = pd.read_csv(path, sep="|", header=None, names=columns, dtype=str, encoding="cp949",
43
+ keep_default_na=False, quoting=csv.QUOTE_NONE)
44
+ return df.apply(lambda col: col.str.strip())
@@ -0,0 +1,22 @@
1
+ """지수선물옵션 종목 마스터(fo_idx_code_mts.mst) 파싱. 내려받기·갱신은 master.py 가 한다.
2
+
3
+ 한 줄 = '|' 로 나뉜 9개 필드 (cp949). 예:
4
+ 5|B01612610|KR4B016C6108|C 202612 610.0|2|00610.00| |2001|KOSPI200
5
+
6
+ 열 이름은 한국투자증권 open-trading-api 의 stocks_info/domestic_index_future_code.py 예제를 따른다
7
+ (예제 열 이름 앞 공백은 뺐다). https://github.com/koreainvestment/open-trading-api
8
+ """
9
+ from __future__ import annotations
10
+
11
+ from pathlib import Path
12
+
13
+ import pandas as pd
14
+
15
+ from kispilot.api.data._mst import parse_pipe_mst
16
+
17
+ COLUMNS = ["상품종류", "단축코드", "표준코드", "한글종목명", "ATM구분",
18
+ "행사가", "월물구분코드", "기초자산단축코드", "기초자산명"]
19
+
20
+
21
+ def parse(mst: Path) -> pd.DataFrame:
22
+ return parse_pipe_mst(mst, COLUMNS)
@@ -1,7 +1,9 @@
1
1
  """KIS 종목·업종 마스터 파일 — 내려받기, 하루 한 번 갱신, 검색.
2
2
 
3
3
  한투가 매일 갱신하는 마스터(.mst.zip)를 받아 CSV 로 바꿔 사용자 데이터 폴더에 둔다.
4
- <데이터 폴더>/data/kospi_code.csv · kosdaq_code.csv · idxcode.csv
4
+ <데이터 폴더>/data/kospi_code.csv · kosdaq_code.csv · idxcode.csv (주식 · 업종)
5
+ <데이터 폴더>/data/fo_idx_code_mts.csv (지수선물옵션 — 주간)
6
+ <데이터 폴더>/data/fo_cme_code.csv · fo_eurex_code.csv (KOSPI200 야간선물 · KRX연계 야간옵션)
5
7
 
6
8
  갱신 규칙
7
9
  - 하루에 한 번. 하루의 경계는 오전 7시 (장 시작 전 갱신분을 받도록).
@@ -21,14 +23,14 @@ import time
21
23
  import zipfile
22
24
  from datetime import datetime, timedelta
23
25
  from pathlib import Path
24
- from typing import Callable, Literal
26
+ from typing import Callable, Literal, get_args
25
27
 
26
28
  import pandas as pd
27
29
  import requests
28
30
 
29
31
  from kispilot.paths import data_dir
30
32
 
31
- Kind = Literal["kospi", "kosdaq", "sector"]
33
+ Kind = Literal["kospi", "kosdaq", "sector", "index_fo", "night_future", "night_option"]
32
34
 
33
35
  _BASE_URL = "https://new.real.download.dws.co.kr/common/master/"
34
36
  _DAY_STARTS_AT = 7 # 이 시각(로컬) 이전에 받은 파일은 하루 지난 것으로 본다
@@ -37,11 +39,14 @@ _log = logging.getLogger("kispilot.master")
37
39
 
38
40
 
39
41
  def _parsers() -> dict[str, tuple[str, str, Callable[[Path], pd.DataFrame]]]:
40
- from kispilot.api.data import kosdaq, kospi, sector
42
+ from kispilot.api.data import index_fo, kosdaq, kospi, night_future, night_option, sector
41
43
  return {
42
44
  "kospi": ("kospi_code.mst.zip", "kospi_code.csv", kospi.parse),
43
45
  "kosdaq": ("kosdaq_code.mst.zip", "kosdaq_code.csv", kosdaq.parse),
44
46
  "sector": ("idxcode.mst.zip", "idxcode.csv", sector.parse),
47
+ "index_fo": ("fo_idx_code_mts.mst.zip", "fo_idx_code_mts.csv", index_fo.parse),
48
+ "night_future": ("fo_cme_code.mst.zip", "fo_cme_code.csv", night_future.parse),
49
+ "night_option": ("fo_eurex_code.mst.zip", "fo_eurex_code.csv", night_option.parse),
45
50
  }
46
51
 
47
52
 
@@ -86,7 +91,7 @@ def refresh(kind: Kind) -> Path:
86
91
 
87
92
  _cache: dict[str, tuple[datetime, pd.DataFrame]] = {}
88
93
  _fail_until: dict[str, float] = {}
89
- _locks = {k: threading.Lock() for k in ("kospi", "kosdaq", "sector")}
94
+ _locks = {k: threading.Lock() for k in get_args(Kind)}
90
95
 
91
96
 
92
97
  def load(kind: Kind) -> pd.DataFrame:
@@ -0,0 +1,33 @@
1
+ """KOSPI200 야간선물 종목 마스터(fo_cme_code.mst) 파싱. 내려받기·갱신은 master.py 가 한다.
2
+
3
+ 예전 CME 연계 야간선물 자리라 파일 이름에 cme 가 남아 있다.
4
+ 한 줄 = cp949 바이트 기준 고정 폭 (121바이트). 예:
5
+ 1A01612 KR4A016C0004F 202612 … 00000.0012001 KOSPI200
6
+
7
+ 열 이름은 한국투자증권 open-trading-api 의 stocks_info/domestic_cme_future_code.py 예제를 따른다.
8
+ 예제의 row[63:72] 는 행사가(8)에 월물구분코드(1)까지 붙여 읽고 기초자산 코드도 한 칸 밀려 있어,
9
+ 야간옵션 마스터(night_option.py)와 같은 꼬리 배치로 고쳐 잡았다.
10
+ https://github.com/koreainvestment/open-trading-api
11
+ """
12
+ from __future__ import annotations
13
+
14
+ from pathlib import Path
15
+
16
+ import pandas as pd
17
+
18
+ from kispilot.api.data._mst import parse_fixed_bytes_mst
19
+
20
+ FIELDS = [
21
+ ("상품종류", 0, 1),
22
+ ("단축코드", 1, 10),
23
+ ("표준코드", 10, 22),
24
+ ("한글종목명", 22, 63),
25
+ ("행사가", 63, 71),
26
+ ("월물구분코드", 71, 72),
27
+ ("기초자산단축코드", 72, 81),
28
+ ("기초자산명", 81, None),
29
+ ]
30
+
31
+
32
+ def parse(mst: Path) -> pd.DataFrame:
33
+ return parse_fixed_bytes_mst(mst, FIELDS)
@@ -0,0 +1,33 @@
1
+ """KRX연계 야간옵션 종목 마스터(fo_eurex_code.mst) 파싱. 내려받기·갱신은 master.py 가 한다.
2
+
3
+ 예전 Eurex 연계 야간옵션 자리라 파일 이름에 eurex 가 남아 있다.
4
+ 한 줄 = cp949 바이트 기준 고정 폭 (121바이트). 예:
5
+ 5B01610745KR4B016A7454C 202610 745.0 … 200745.00 2001 KOSPI200
6
+
7
+ 필드 위치·열 이름은 한국투자증권 open-trading-api 의 stocks_info/domestic_eurex_option_code.py 예제를 따르되,
8
+ 예제는 문자 위치로 자른 뒤 lstrip() 으로 어긋남을 메꾸므로 여기서는 바이트 위치로 고쳐 잡았다.
9
+ 월물구분코드 자리(바이트 71)는 옵션이라 비어 있어 뺐다.
10
+ https://github.com/koreainvestment/open-trading-api
11
+ """
12
+ from __future__ import annotations
13
+
14
+ from pathlib import Path
15
+
16
+ import pandas as pd
17
+
18
+ from kispilot.api.data._mst import parse_fixed_bytes_mst
19
+
20
+ FIELDS = [
21
+ ("상품종류", 0, 1),
22
+ ("단축코드", 1, 10),
23
+ ("표준코드", 10, 22),
24
+ ("한글종목명", 22, 59),
25
+ ("ATM구분", 62, 63),
26
+ ("행사가", 63, 71),
27
+ ("기초자산단축코드", 72, 81),
28
+ ("기초자산명", 81, None),
29
+ ]
30
+
31
+
32
+ def parse(mst: Path) -> pd.DataFrame:
33
+ return parse_fixed_bytes_mst(mst, FIELDS)
@@ -0,0 +1,19 @@
1
+ """국내선물옵션(주간 · 야간) API 모음.
2
+
3
+ from kispilot.api.futureoption import (
4
+ inquire_price, inquire_asking_price,
5
+ inquire_daily_fuopchartprice, inquire_time_fuopchartprice,
6
+ )
7
+ """
8
+
9
+ from .futureoption_inquire_price import inquire_price
10
+ from .futureoption_inquire_asking_price import inquire_asking_price
11
+ from .futureoption_inquire_daily_fuopchartprice import inquire_daily_fuopchartprice
12
+ from .futureoption_inquire_time_fuopchartprice import inquire_time_fuopchartprice
13
+
14
+ __all__ = [
15
+ "inquire_price",
16
+ "inquire_asking_price",
17
+ "inquire_daily_fuopchartprice",
18
+ "inquire_time_fuopchartprice",
19
+ ]
@@ -0,0 +1,142 @@
1
+ # 선물옵션 시세호가[v1_국내선물-007]
2
+ from dataclasses import dataclass
3
+ from typing import Literal, Optional
4
+
5
+ from kispilot.api.config import DOMAIN, REAL_APPKEY, REAL_APP_SECRET, PAPER_APPKEY, PAPER_APP_SECRET
6
+ from kispilot.api.oauth.kis_token import load_token
7
+ from kispilot.api.utils.http_session import get_session
8
+
9
+ URL = "/uapi/domestic-futureoption/v1/quotations/inquire-asking-price"
10
+ # ※ 실시간 데이터가 필요하면 웹소켓 API를 이용할 것.
11
+
12
+ _TR_ID = "FHMIF10010000" # 실전/모의 동일
13
+
14
+
15
+ # ── DataClass 정의 ──────────────────────────────────────────
16
+
17
+ @dataclass
18
+ class ResponseBodyOutput1:
19
+ hts_kor_isnm: Optional[str] = None # HTS 한글 종목명
20
+ futs_prpr: Optional[str] = None # 선물 현재가
21
+ prdy_vrss_sign: Optional[str] = None # 전일 대비 부호 (1 상한, 2 상승, 3 보합, 4 하한, 5 하락)
22
+ futs_prdy_vrss: Optional[str] = None # 선물 전일 대비
23
+ futs_prdy_ctrt: Optional[str] = None # 선물 전일 대비율
24
+ acml_vol: Optional[str] = None # 누적 거래량
25
+ futs_prdy_clpr: Optional[str] = None # 선물 전일 종가
26
+ futs_shrn_iscd: Optional[str] = None # 선물 단축 종목코드
27
+
28
+
29
+ @dataclass
30
+ class ResponseBodyOutput2:
31
+ futs_askp1: Optional[str] = None # 선물 매도호가1
32
+ futs_askp2: Optional[str] = None # 선물 매도호가2
33
+ futs_askp3: Optional[str] = None # 선물 매도호가3
34
+ futs_askp4: Optional[str] = None # 선물 매도호가4
35
+ futs_askp5: Optional[str] = None # 선물 매도호가5
36
+ futs_bidp1: Optional[str] = None # 선물 매수호가1
37
+ futs_bidp2: Optional[str] = None # 선물 매수호가2
38
+ futs_bidp3: Optional[str] = None # 선물 매수호가3
39
+ futs_bidp4: Optional[str] = None # 선물 매수호가4
40
+ futs_bidp5: Optional[str] = None # 선물 매수호가5
41
+ askp_rsqn1: Optional[str] = None # 매도호가 잔량1
42
+ askp_rsqn2: Optional[str] = None # 매도호가 잔량2
43
+ askp_rsqn3: Optional[str] = None # 매도호가 잔량3
44
+ askp_rsqn4: Optional[str] = None # 매도호가 잔량4
45
+ askp_rsqn5: Optional[str] = None # 매도호가 잔량5
46
+ bidp_rsqn1: Optional[str] = None # 매수호가 잔량1
47
+ bidp_rsqn2: Optional[str] = None # 매수호가 잔량2
48
+ bidp_rsqn3: Optional[str] = None # 매수호가 잔량3
49
+ bidp_rsqn4: Optional[str] = None # 매수호가 잔량4
50
+ bidp_rsqn5: Optional[str] = None # 매수호가 잔량5
51
+ askp_csnu1: Optional[str] = None # 매도호가 건수1
52
+ askp_csnu2: Optional[str] = None # 매도호가 건수2
53
+ askp_csnu3: Optional[str] = None # 매도호가 건수3
54
+ askp_csnu4: Optional[str] = None # 매도호가 건수4
55
+ askp_csnu5: Optional[str] = None # 매도호가 건수5
56
+ bidp_csnu1: Optional[str] = None # 매수호가 건수1
57
+ bidp_csnu2: Optional[str] = None # 매수호가 건수2
58
+ bidp_csnu3: Optional[str] = None # 매수호가 건수3
59
+ bidp_csnu4: Optional[str] = None # 매수호가 건수4
60
+ bidp_csnu5: Optional[str] = None # 매수호가 건수5
61
+ total_askp_rsqn: Optional[str] = None # 총 매도호가 잔량
62
+ total_bidp_rsqn: Optional[str] = None # 총 매수호가 잔량
63
+ total_askp_csnu: Optional[str] = None # 총 매도호가 건수
64
+ total_bidp_csnu: Optional[str] = None # 총 매수호가 건수
65
+ aspr_acpt_hour: Optional[str] = None # 호가 접수 시간 (HHMMSS)
66
+
67
+
68
+ @dataclass
69
+ class ResponseBody:
70
+ rt_cd: str # 성공 실패 여부
71
+ msg_cd: str # 응답코드
72
+ msg1: str # 응답메세지
73
+ output1: ResponseBodyOutput1 # 시세 요약
74
+ output2: ResponseBodyOutput2 # 매도/매수 5단계 호가 (문서는 배열이라 하지만 실제 응답은 객체 하나)
75
+
76
+
77
+ # ── 요청 함수 ───────────────────────────────────────────────
78
+
79
+ def inquire_asking_price(
80
+ code: str,
81
+ market_div: Literal["F", "O", "JF", "JO", "CF", "CM", "EU"],
82
+ mode: Literal["real", "paper"] = "real",
83
+ ) -> ResponseBody:
84
+ """선물옵션 시세호가(매도/매수 5단계 호가·잔량·건수)를 조회한다.
85
+
86
+ Args:
87
+ code: 입력 종목코드(FID_INPUT_ISCD), 선물옵션 단축코드(ex A01612 KOSPI200 선물 2026년 12월물).
88
+ market_div: 조건 시장 분류 코드(FID_COND_MRKT_DIV_CODE). F:지수선물, O:지수옵션, JF:주식선물,
89
+ JO:주식옵션, CF:상품선물(금·국채·달러), CM:야간선물, EU:야간옵션.
90
+ mode: "real"(실전투자) 또는 "paper"(모의투자). 기본값 "real".
91
+
92
+ Returns:
93
+ rt_cd/msg_cd/msg1과 시세 요약(output1), 매도/매수 호가(output2)를 담은 ResponseBody.
94
+ """
95
+ token = load_token(mode)
96
+ if mode == "real":
97
+ app_key, app_secret = REAL_APPKEY, REAL_APP_SECRET
98
+ else:
99
+ app_key, app_secret = PAPER_APPKEY, PAPER_APP_SECRET
100
+
101
+ headers = {
102
+ "content-type": "application/json; charset=utf-8",
103
+ "authorization": f"Bearer {token}",
104
+ "appkey": app_key,
105
+ "appsecret": app_secret,
106
+ "tr_id": _TR_ID,
107
+ "custtype": "P",
108
+ }
109
+ params = {
110
+ "FID_COND_MRKT_DIV_CODE": market_div,
111
+ "FID_INPUT_ISCD": code,
112
+ }
113
+ response = get_session().get(DOMAIN[mode] + URL, headers=headers, params=params, timeout=10)
114
+ raw = response.json()
115
+
116
+ # 에러 응답(rt_cd != "0")은 output1/output2 키가 없거나 null일 수 있어 안전 파싱.
117
+ fields1 = set(ResponseBodyOutput1.__dataclass_fields__)
118
+ raw_output1 = raw.get("output1") or {}
119
+ output1 = ResponseBodyOutput1(**{k: v for k, v in raw_output1.items() if k in fields1})
120
+
121
+ fields2 = set(ResponseBodyOutput2.__dataclass_fields__)
122
+ raw_output2 = raw.get("output2") or {}
123
+ output2 = ResponseBodyOutput2(**{k: v for k, v in raw_output2.items() if k in fields2})
124
+
125
+ return ResponseBody(
126
+ rt_cd=raw.get("rt_cd", ""),
127
+ msg_cd=raw.get("msg_cd", ""),
128
+ msg1=raw.get("msg1", ""),
129
+ output1=output1,
130
+ output2=output2,
131
+ )
132
+
133
+
134
+ # ── 실행 ────────────────────────────────────────────────────
135
+
136
+ if __name__ == "__main__":
137
+ result = inquire_asking_price(code="A01612", market_div="F")
138
+ if result.rt_cd != "0":
139
+ print(f"조회 실패: {result.msg_cd} - {result.msg1}")
140
+ else:
141
+ print(result.output1)
142
+ print(result.output2)