programgarden-core 2.6.3__tar.gz → 2.7.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 (89) hide show
  1. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/PKG-INFO +1 -1
  2. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/i18n/locales/en.json +4 -2
  3. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/i18n/locales/ko.json +4 -2
  4. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/backtest_stock.py +56 -8
  5. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/pyproject.toml +1 -1
  6. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/README.md +0 -0
  7. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/__init__.py +0 -0
  8. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/bases/__init__.py +0 -0
  9. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/bases/client.py +0 -0
  10. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/bases/components.py +0 -0
  11. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/bases/listener.py +0 -0
  12. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/bases/mixins.py +0 -0
  13. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/bases/products.py +0 -0
  14. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/bases/sql.py +0 -0
  15. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/bases/storage.py +0 -0
  16. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/code_node.py +0 -0
  17. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/exceptions.py +0 -0
  18. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/expression/__init__.py +0 -0
  19. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/expression/evaluator.py +0 -0
  20. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/expression/reference.py +0 -0
  21. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/i18n/__init__.py +0 -0
  22. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/i18n/translator.py +0 -0
  23. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/korea_alias.py +0 -0
  24. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/market_calendar.py +0 -0
  25. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/models/__init__.py +0 -0
  26. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/models/connection_rule.py +0 -0
  27. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/models/credential.py +0 -0
  28. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/models/edge.py +0 -0
  29. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/models/event.py +0 -0
  30. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/models/exchange.py +0 -0
  31. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/models/field_binding.py +0 -0
  32. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/models/job.py +0 -0
  33. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/models/order_diagnostics.py +0 -0
  34. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/models/plugin_resource.py +0 -0
  35. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/models/resilience.py +0 -0
  36. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/models/resource.py +0 -0
  37. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/models/validation.py +0 -0
  38. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/models/workflow.py +0 -0
  39. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/__init__.py +0 -0
  40. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/account_futures.py +0 -0
  41. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/account_korea_stock.py +0 -0
  42. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/account_stock.py +0 -0
  43. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/ai.py +0 -0
  44. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/backtest.py +0 -0
  45. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/backtest_futures.py +0 -0
  46. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/backtest_korea_stock.py +0 -0
  47. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/base.py +0 -0
  48. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/broker.py +0 -0
  49. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/calculation.py +0 -0
  50. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/code.py +0 -0
  51. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/condition.py +0 -0
  52. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/contract_info_futures.py +0 -0
  53. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/data.py +0 -0
  54. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/data_futures.py +0 -0
  55. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/data_korea_stock.py +0 -0
  56. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/data_stock.py +0 -0
  57. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/display.py +0 -0
  58. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/event.py +0 -0
  59. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/fundamental_korea_stock.py +0 -0
  60. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/fundamental_stock.py +0 -0
  61. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/infra.py +0 -0
  62. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/open_orders_futures.py +0 -0
  63. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/open_orders_korea_stock.py +0 -0
  64. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/open_orders_stock.py +0 -0
  65. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/order.py +0 -0
  66. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/orderable_quantity_futures.py +0 -0
  67. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/portfolio.py +0 -0
  68. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/ranking_korea_stock.py +0 -0
  69. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/ranking_stock.py +0 -0
  70. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/realtime_futures.py +0 -0
  71. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/realtime_korea_stock.py +0 -0
  72. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/realtime_stock.py +0 -0
  73. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/risk.py +0 -0
  74. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/session_gate.py +0 -0
  75. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/symbol.py +0 -0
  76. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/symbol_futures.py +0 -0
  77. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/symbol_korea_stock.py +0 -0
  78. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/symbol_stock.py +0 -0
  79. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/nodes/trigger.py +0 -0
  80. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/presets/__init__.py +0 -0
  81. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/presets/news_analyst.json +0 -0
  82. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/presets/risk_manager.json +0 -0
  83. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/presets/strategist.json +0 -0
  84. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/presets/technical_analyst.json +0 -0
  85. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/registry/__init__.py +0 -0
  86. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/registry/credential_registry.py +0 -0
  87. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/registry/node_registry.py +0 -0
  88. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/registry/plugin_registry.py +0 -0
  89. {programgarden_core-2.6.3 → programgarden_core-2.7.0}/programgarden_core/retry_executor.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: programgarden-core
3
- Version: 2.6.3
3
+ Version: 2.7.0
4
4
  Summary: ProgramGarden Core - 노드 기반 DSL 핵심 타입 정의
5
5
  License-Expression: AGPL-3.0-or-later
6
6
  Author: 프로그램동산
@@ -144,7 +144,7 @@
144
144
  "nodes.OverseasStockBrokerNode.name": "Stock Broker",
145
145
  "nodes.OverseasStockCancelOrderNode.description": "Cancels a pending US stock order by its original order ID. Requires original_order_id from OverseasStockOpenOrdersNode or OverseasStockRealOrderEventNode. Outputs cancel result and cancelled order ID. Rate-limited to 5-second minimum interval. Typical connection: StockOpenOrdersNode → StockCancelOrderNode, or StockRealOrderEventNode → StockCancelOrderNode.",
146
146
  "nodes.OverseasStockCancelOrderNode.name": "Stock Cancel Order",
147
- "nodes.OverseasStockHistoricalDataNode.description": "Fetches historical OHLCV (Open, High, Low, Close, Volume) chart data for overseas stocks over a specified date range. Uses LS g3204 for daily, weekly, monthly and yearly bars. Intraday g3203 is unsupported. Enable 'adjust' for split/dividend-adjusted prices (recommended for backtesting). Auto-iterates when previous node outputs multiple symbols. Requires an upstream OverseasStockBrokerNode. Typical connection: WatchlistNode → StockHistoricalDataNode → ConditionNode or → BacktestEngineNode. Supported exchanges: NYSE, NASDAQ, AMEX. Can be used as an AI Agent tool.",
147
+ "nodes.OverseasStockHistoricalDataNode.description": "Fetches historical OHLCV (Open, High, Low, Close, Volume) chart data for overseas stocks over a specified date range. Uses LS g3204 for daily, weekly, monthly and yearly bars and LS g3203 for 1/5/10/15/30/60-minute bars (one page of the newest up to 500 bars). Enable 'adjust' for split/dividend-adjusted prices (recommended for backtesting). Auto-iterates when previous node outputs multiple symbols. Requires an upstream OverseasStockBrokerNode. Typical connection: WatchlistNode → StockHistoricalDataNode → ConditionNode or → BacktestEngineNode. Supported exchanges: NYSE, NASDAQ, AMEX. Can be used as an AI Agent tool.",
148
148
  "nodes.OverseasStockHistoricalDataNode.name": "Stock Historical Data",
149
149
  "nodes.OverseasStockFundamentalNode.description": "Fetches fundamental financial data for overseas stocks via LS Securities API. Provides 16 metrics including PER, EPS, PBR, market capitalization, dividend yield, 52-week high/low, and more. Auto-iterates when previous node outputs multiple symbols. Requires an upstream OverseasStockBrokerNode. Typical connection: WatchlistNode → StockFundamentalNode → ConditionNode (for value-based screening). Supported exchanges: NYSE, NASDAQ, AMEX. Can be used as an AI Agent tool.",
150
150
  "nodes.OverseasStockFundamentalNode.name": "Stock Fundamentals",
@@ -430,7 +430,7 @@
430
430
  "fields.OverseasStockHistoricalDataNode.adjust.short": "Apply adjusted price",
431
431
  "fields.OverseasStockHistoricalDataNode.end_date": "End date (YYYYMMDD)",
432
432
  "fields.OverseasStockHistoricalDataNode.end_date.help_text": "e.g., 20241231. With binding: {{ date.today(format='yyyymmdd') }}",
433
- "fields.OverseasStockHistoricalDataNode.interval": "LS g3204 interval (1d, 1w, 1M, 1Y); intraday is unsupported",
433
+ "fields.OverseasStockHistoricalDataNode.interval": "Bar size: 1d, 1w, 1M, 1Y (LS g3204) or 1m, 5m, 10m, 15m, 30m, 60m minute bars (LS g3203, newest up to 500 bars)",
434
434
  "fields.OverseasStockHistoricalDataNode.start_date": "Start date (YYYYMMDD)",
435
435
  "fields.OverseasStockHistoricalDataNode.start_date.help_text": "e.g., 20240101. With binding: {{ date.ago(30, format='yyyymmdd') }}",
436
436
  "fields.OverseasStockHistoricalDataNode.symbol": "Enter the symbol code to query",
@@ -1059,6 +1059,7 @@
1059
1059
  "enums.kr_price_type.conditional_limit": "Conditional Limit",
1060
1060
  "enums.kr_price_type.limit": "Limit",
1061
1061
  "enums.kr_price_type.market": "Market",
1062
+ "enums.interval.10m": "10 Minutes",
1062
1063
  "enums.interval.15m": "15 Minutes",
1063
1064
  "enums.interval.1M": "1 Month",
1064
1065
  "enums.interval.1Y": "1 year",
@@ -1069,6 +1070,7 @@
1069
1070
  "enums.interval.1m": "1 Minute",
1070
1071
  "enums.interval.1w": "1 Week",
1071
1072
  "enums.interval.5m": "5 Minutes",
1073
+ "enums.interval.60m": "60 Minutes",
1072
1074
  "enums.operator.all": "All Match (AND) - Every condition must pass",
1073
1075
  "enums.operator.any": "Any Match (OR) - At least one must pass",
1074
1076
  "enums.operator.at_least": "At Least N - threshold or more must pass",
@@ -144,7 +144,7 @@
144
144
  "nodes.OverseasStockBrokerNode.name": "해외주식 브로커",
145
145
  "nodes.OverseasStockCancelOrderNode.description": "미국 주식 미체결 주문을 원래 주문 ID로 취소합니다. OverseasStockOpenOrdersNode 또는 OverseasStockRealOrderEventNode에서 original_order_id를 받아야 합니다. 출력: 취소 결과, 취소된 주문 ID. 최소 5초 간격 제한 적용. 일반적인 연결: StockOpenOrdersNode → StockCancelOrderNode 또는 StockRealOrderEventNode → StockCancelOrderNode.",
146
146
  "nodes.OverseasStockCancelOrderNode.name": "해외주식 취소주문",
147
- "nodes.OverseasStockHistoricalDataNode.description": "지정 기간의 해외주식 과거 OHLCV(시가, 고가, 저가, 종가, 거래량) 차트 데이터를 조회합니다. LS g3204로 일봉·주봉·월봉·연봉을 조회합니다. 분봉·시간봉(g3203)은 지원하지 않습니다. 수정주가(주식 분할/배당 반영) 활성화 권장(백테스트용). 이전 노드가 여러 종목을 출력하면 자동 반복 실행. 상위 OverseasStockBrokerNode 연결 필수. 일반적인 연결: WatchlistNode → StockHistoricalDataNode → ConditionNode 또는 → BacktestEngineNode. 지원 거래소: NYSE, NASDAQ, AMEX. AI Agent 도구로 사용 가능.",
147
+ "nodes.OverseasStockHistoricalDataNode.description": "지정 기간의 해외주식 과거 OHLCV(시가, 고가, 저가, 종가, 거래량) 차트 데이터를 조회합니다. LS g3204로 일봉·주봉·월봉·연봉을, LS g3203으로 1·5·10·15·30·60분봉(최근 최대 500개 한 페이지)을 조회합니다. 수정주가(주식 분할/배당 반영) 활성화 권장(백테스트용). 이전 노드가 여러 종목을 출력하면 자동 반복 실행. 상위 OverseasStockBrokerNode 연결 필수. 일반적인 연결: WatchlistNode → StockHistoricalDataNode → ConditionNode 또는 → BacktestEngineNode. 지원 거래소: NYSE, NASDAQ, AMEX. AI Agent 도구로 사용 가능.",
148
148
  "nodes.OverseasStockHistoricalDataNode.name": "해외주식 과거데이터",
149
149
  "nodes.OverseasStockFundamentalNode.description": "LS증권 API로 해외주식 펀더멘털 재무 데이터를 조회합니다. PER, EPS, PBR, 시가총액, 배당수익률, 52주 고/저가 등 16개 지표를 제공합니다. 이전 노드가 여러 종목을 출력하면 자동 반복 실행. 상위 OverseasStockBrokerNode 연결 필수. 일반적인 연결: WatchlistNode → StockFundamentalNode → ConditionNode (가치 기반 스크리닝). 지원 거래소: NYSE, NASDAQ, AMEX. AI Agent 도구로 사용 가능.",
150
150
  "nodes.OverseasStockFundamentalNode.name": "해외주식 종목정보",
@@ -430,7 +430,7 @@
430
430
  "fields.OverseasStockHistoricalDataNode.adjust.short": "수정주가 적용 여부",
431
431
  "fields.OverseasStockHistoricalDataNode.end_date": "조회 종료일 (YYYYMMDD)",
432
432
  "fields.OverseasStockHistoricalDataNode.end_date.help_text": "예: 20241231. 바인딩 시 {{ date.today(format='yyyymmdd') }} 사용 가능",
433
- "fields.OverseasStockHistoricalDataNode.interval": "LS g3204 봉 종류 (1d, 1w, 1M, 1Y). 분봉·시간봉 미지원",
433
+ "fields.OverseasStockHistoricalDataNode.interval": "봉 종류: 1d, 1w, 1M, 1Y (LS g3204) 또는 1m, 5m, 10m, 15m, 30m, 60m 분봉 (LS g3203, 최근 최대 500개)",
434
434
  "fields.OverseasStockHistoricalDataNode.start_date": "조회 시작일 (YYYYMMDD)",
435
435
  "fields.OverseasStockHistoricalDataNode.start_date.help_text": "예: 20240101. 바인딩 시 {{ date.ago(30, format='yyyymmdd') }} 사용 가능",
436
436
  "fields.OverseasStockHistoricalDataNode.symbol": "조회할 종목 코드를 입력하세요",
@@ -1059,6 +1059,7 @@
1059
1059
  "enums.kr_price_type.conditional_limit": "조건부지정가 (Conditional Limit)",
1060
1060
  "enums.kr_price_type.limit": "지정가 (Limit)",
1061
1061
  "enums.kr_price_type.market": "시장가 (Market)",
1062
+ "enums.interval.10m": "10분",
1062
1063
  "enums.interval.15m": "15분",
1063
1064
  "enums.interval.1M": "1개월",
1064
1065
  "enums.interval.1Y": "1년",
@@ -1069,6 +1070,7 @@
1069
1070
  "enums.interval.1m": "1분",
1070
1071
  "enums.interval.1w": "1주",
1071
1072
  "enums.interval.5m": "5분",
1073
+ "enums.interval.60m": "60분",
1072
1074
  "enums.operator.all": "전체 만족 (AND) - 모든 조건 통과 필요",
1073
1075
  "enums.operator.any": "하나 이상 (OR) - 1개만 통과해도 OK",
1074
1076
  "enums.operator.at_least": "최소 N개 이상 - threshold 개수 이상 통과",
@@ -65,9 +65,10 @@ class OverseasStockHistoricalDataNode(BaseNode):
65
65
  default="{{ date.today(format='yyyymmdd') }}",
66
66
  description="End date (YYYY-MM-DD or {{ date.today(format='yyyymmdd') }})",
67
67
  )
68
- interval: Literal["1d", "1w", "1M", "1Y"] = Field(
68
+ interval: Literal["1d", "1w", "1M", "1Y", "1m", "5m", "10m", "15m", "30m", "60m"] = Field(
69
69
  default="1d",
70
- description="LS g3204 interval: daily, weekly, monthly or yearly. Intraday is unsupported.",
70
+ description=("Bar size: 1d, 1w, 1M, 1Y read LS g3204; 1m, 5m, 10m, 15m, 30m, 60m read LS g3203 "
71
+ "minute bars (one page, newest up to 500 bars)."),
71
72
  )
72
73
  adjust: bool = Field(
73
74
  default=False,
@@ -81,6 +82,7 @@ class OverseasStockHistoricalDataNode(BaseNode):
81
82
  _usage: ClassVar[Dict[str, Any]] = {
82
83
  "when_to_use": [
83
84
  "Retrieve daily, weekly, monthly or yearly OHLCV history for a US-listed stock to compute technical indicators or run backtests",
85
+ "Retrieve 1/5/10/15/30/60-minute bars of a US-listed stock for an intraday indicator (one page of the newest bars)",
84
86
  "Feed time-series data into ConditionNode plugins (RSI, MACD, Bollinger, etc.) that require a `data` list of candles",
85
87
  "Use `{{ date.ago(N, format='yyyymmdd') }}` for start_date to get a rolling lookback window without hardcoding dates",
86
88
  ],
@@ -97,7 +99,9 @@ class OverseasStockHistoricalDataNode(BaseNode):
97
99
  }
98
100
  _features: ClassVar[List[str]] = [
99
101
  "Returns a list of OHLCV candles in `value.time_series`: [{date, open, high, low, close, volume}, ...]",
100
- "Supports intervals: 1d, 1w, 1M, 1Y through LS g3204; intraday history is unsupported",
102
+ "Supports intervals: 1d, 1w, 1M, 1Y through LS g3204 and 1m, 5m, 10m, 15m, 30m, 60m through LS g3203",
103
+ "A minute interval reads ONE g3203 page: the newest up to 500 bars at or before end_date within start_date..end_date; a longer range is not completed by paging",
104
+ "A minute bar's date is YYYYMMDDHHMMSS in the exchange's local time as LS labels it; pre-market, after-hours and overnight-session bars are included as LS returns them",
101
105
  "start_date / end_date accept YYYYMMDD strings or expression namespace calls: `{{ date.ago(30, format='yyyymmdd') }}`",
102
106
  "adjust=True applies split/dividend-adjusted prices for accurate long-term backtesting",
103
107
  "is_tool_enabled=True — AI Agent can fetch historical data autonomously for technical analysis",
@@ -156,12 +160,48 @@ class OverseasStockHistoricalDataNode(BaseNode):
156
160
  },
157
161
  "expected_output": "value port: {symbol, exchange, time_series: [{date, open, high, low, close, volume}, ...]}. RSI is computed from time_series.",
158
162
  },
163
+ {
164
+ "title": "15-minute bars for an intraday RSI",
165
+ "description": "Fetch the newest 15-minute bars of NVDA (LS g3203, one page of up to 500 bars) and compute RSI on them. Bar dates are YYYYMMDDHHMMSS in exchange local time and include extended-hours bars.",
166
+ "workflow_snippet": {
167
+ "id": "overseas_stock_minute_rsi",
168
+ "name": "Minute-bar RSI Signal",
169
+ "nodes": [
170
+ {"id": "start", "type": "StartNode"},
171
+ {"id": "broker", "type": "OverseasStockBrokerNode", "credential_id": "broker_cred", "paper_trading": False},
172
+ {"id": "split", "type": "SplitNode", "array": [{"symbol": "NVDA", "exchange": "NASDAQ"}]},
173
+ {"id": "historical", "type": "OverseasStockHistoricalDataNode", "symbol": "{{ nodes.split.item }}", "start_date": "{{ date.ago(5, format='yyyymmdd') }}", "end_date": "{{ date.today(format='yyyymmdd') }}", "interval": "15m"},
174
+ {"id": "condition", "type": "ConditionNode", "plugin": "RSI", "items": {"from": "{{ item.time_series }}", "extract": {"symbol": "{{ item.symbol }}", "exchange": "{{ item.exchange }}", "date": "{{ row.date }}", "close": "{{ row.close }}"}}, "fields": {"period": 14, "threshold": 30, "direction": "below"}},
175
+ {"id": "split_results", "type": "AggregateNode", "mode": "collect"},
176
+ ],
177
+ "edges": [
178
+ {"from": "start", "to": "broker"},
179
+ {"from": "broker", "to": "split"},
180
+ {"from": "split", "to": "historical"},
181
+ {"from": "broker", "to": "historical"},
182
+ {"from": "historical", "to": "condition"},
183
+ {"from": "condition", "to": "split_results"},
184
+ ],
185
+ "credentials": [
186
+ {
187
+ "credential_id": "broker_cred",
188
+ "type": "broker_ls_overseas_stock",
189
+ "data": [
190
+ {"key": "appkey", "value": "", "type": "password", "label": "App Key"},
191
+ {"key": "appsecret", "value": "", "type": "password", "label": "App Secret"},
192
+ ],
193
+ }
194
+ ],
195
+ },
196
+ "expected_output": "value port: {symbol, exchange, time_series: [{date: 'YYYYMMDDHHMMSS', open, high, low, close, volume}, ...]} oldest first. RSI is computed from the 15-minute closes.",
197
+ },
159
198
  ]
160
199
  _node_guide: ClassVar[Dict[str, Any]] = {
161
200
  "input_handling": (
162
201
  "The `symbol` field takes a single {exchange, symbol} dict — bind to `{{ nodes.split.item }}` in a per-symbol loop. "
163
202
  "start_date / end_date accept 'YYYYMMDD' strings or `{{ date.ago(N, format='yyyymmdd') }}` expressions. "
164
- "Supported intervals: 1d, 1w, 1M, 1Y through LS g3204. Intraday g3203 is not connected to this node."
203
+ "Supported intervals: 1d, 1w, 1M, 1Y through LS g3204; 1m, 5m, 10m, 15m, 30m, 60m through LS g3203 "
204
+ "(one page of the newest up to 500 bars, date = YYYYMMDDHHMMSS exchange local time)."
165
205
  ),
166
206
  "output_consumption": (
167
207
  "The `value` port emits a dict: {symbol, exchange, time_series: [{date, open, high, low, close, volume}, ...]}. "
@@ -177,9 +217,11 @@ class OverseasStockHistoricalDataNode(BaseNode):
177
217
  "pitfalls": [
178
218
  "`symbol: {{ item }}` / `{{ nodes.<split>.item }}` resolves only inside a per-symbol loop (auto-iterate over an upstream array, or a SplitNode branch). If the upstream array is empty for this run the node logs `No symbols to fetch` and returns an empty series — normal no-signal, not a defect. A `No symbols provided` WARNING means the symbol source is missing or the binding did not resolve",
179
219
  "Access time_series via `{{ nodes.historical.value.time_series }}` — the value port is a dict, not a plain list",
180
- "Intraday intervals (1m/5m/15m/1h) are unsupported; never substitute daily bars or invent a g3203 node connection",
220
+ "Minute intervals are 1m, 5m, 10m, 15m, 30m and 60m (not 1h or 1min); daily bars are never a substitute for an intraday strategy",
221
+ "Minute bars include every session LS returns: pre-market, after-hours and the overnight session from 20:00 local time of the previous day (a Sunday date can appear); the regular session is 09:30-16:00 exchange local time, so filter by the time part of `date` when a strategy needs the regular session only",
222
+ "`adjust` has no effect on minute intervals: LS g3203 has no adjusted-price option, minute bars are the prices as traded",
181
223
  "adjust=False (default) returns unadjusted prices; set True when comparing long-term price levels across splits",
182
- "The current executor requests one g3204 page; it does not expose response-time, continuation-completion or candle-finality evidence",
224
+ "The executor requests one g3204 or g3203 page; it does not expose response-time, continuation-completion or candle-finality evidence (the newest minute bar may still be forming)",
183
225
  ],
184
226
  }
185
227
 
@@ -300,12 +342,18 @@ class OverseasStockHistoricalDataNode(BaseNode):
300
342
  description="i18n:fields.OverseasStockHistoricalDataNode.interval",
301
343
  default="1d",
302
344
  required=True,
303
- enum_values=["1d", "1w", "1M", "1Y"],
345
+ enum_values=["1d", "1w", "1M", "1Y", "1m", "5m", "10m", "15m", "30m", "60m"],
304
346
  enum_labels={
305
347
  "1d": "i18n:enums.interval.1d",
306
348
  "1w": "i18n:enums.interval.1w",
307
349
  "1M": "i18n:enums.interval.1M",
308
- "1Y": "i18n:enums.interval.1Y"
350
+ "1Y": "i18n:enums.interval.1Y",
351
+ "1m": "i18n:enums.interval.1m",
352
+ "5m": "i18n:enums.interval.5m",
353
+ "10m": "i18n:enums.interval.10m",
354
+ "15m": "i18n:enums.interval.15m",
355
+ "30m": "i18n:enums.interval.30m",
356
+ "60m": "i18n:enums.interval.60m",
309
357
  },
310
358
  category=FieldCategory.PARAMETERS,
311
359
  expression_mode=ExpressionMode.FIXED_ONLY,
@@ -5,7 +5,7 @@ authors = [
5
5
  homepage = "https://programgarden.com"
6
6
  requires-python = ">=3.12"
7
7
  name = "programgarden-core"
8
- version = "2.6.3"
8
+ version = "2.7.0"
9
9
  license = "AGPL-3.0-or-later"
10
10
  description = "ProgramGarden Core - 노드 기반 DSL 핵심 타입 정의"
11
11
  readme = "README.md"