programgarden-core 1.2.0__tar.gz → 1.4.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.
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/PKG-INFO +1 -1
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/i18n/locales/en.json +41 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/i18n/locales/ko.json +41 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/models/edge.py +19 -8
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/__init__.py +7 -4
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/account_futures.py +2 -2
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/account_stock.py +2 -2
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/ai.py +1 -1
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/base.py +54 -1
- programgarden_core-1.4.0/programgarden_core/nodes/fundamental_stock.py +91 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/infra.py +104 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/realtime_futures.py +2 -2
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/realtime_stock.py +2 -2
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/registry/node_registry.py +6 -4
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/pyproject.toml +1 -1
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/README.md +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/__init__.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/bases/__init__.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/bases/client.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/bases/components.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/bases/listener.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/bases/mixins.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/bases/products.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/bases/sql.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/bases/storage.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/exceptions.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/expression/__init__.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/expression/evaluator.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/i18n/__init__.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/i18n/translator.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/korea_alias.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/models/__init__.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/models/connection_rule.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/models/credential.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/models/event.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/models/exchange.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/models/field_binding.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/models/job.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/models/plugin_resource.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/models/resilience.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/models/resource.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/models/workflow.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/backtest.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/backtest_futures.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/backtest_stock.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/broker.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/calculation.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/condition.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/data.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/data_futures.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/data_stock.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/display.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/event.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/open_orders_futures.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/open_orders_stock.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/order.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/portfolio.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/risk.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/symbol.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/symbol_futures.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/symbol_stock.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/trigger.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/presets/__init__.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/presets/news_analyst.json +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/presets/risk_manager.json +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/presets/strategist.json +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/presets/technical_analyst.json +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/registry/__init__.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/registry/credential_registry.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/registry/dynamic_node_registry.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/registry/plugin_registry.py +0 -0
- {programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/retry_executor.py +0 -0
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/i18n/locales/en.json
RENAMED
|
@@ -36,6 +36,8 @@
|
|
|
36
36
|
"nodes.AIAgentNode.name": "AI Agent",
|
|
37
37
|
"nodes.AggregateNode.description": "Collect individual items into a list. Use with SplitNode.",
|
|
38
38
|
"nodes.AggregateNode.name": "Aggregate",
|
|
39
|
+
"nodes.IfNode.description": "Branch execution flow based on a condition (if/else)",
|
|
40
|
+
"nodes.IfNode.name": "If Branch",
|
|
39
41
|
"nodes.AlertNode.description": "Send notifications (email, SMS, webhook).",
|
|
40
42
|
"nodes.AlertNode.name": "Alert",
|
|
41
43
|
"nodes.BacktestEngineNode.description": "Run backtest with signals and historical data, calculate performance metrics.",
|
|
@@ -110,6 +112,8 @@
|
|
|
110
112
|
"nodes.OverseasStockCancelOrderNode.name": "Stock Cancel Order",
|
|
111
113
|
"nodes.OverseasStockHistoricalDataNode.description": "Get historical OHLCV data for overseas stocks. (NYSE, NASDAQ, AMEX)",
|
|
112
114
|
"nodes.OverseasStockHistoricalDataNode.name": "Stock Historical Data",
|
|
115
|
+
"nodes.OverseasStockFundamentalNode.description": "Get fundamental data including PER, EPS, market cap, and 52-week high/low for overseas stocks. (NYSE, NASDAQ, AMEX)",
|
|
116
|
+
"nodes.OverseasStockFundamentalNode.name": "Stock Fundamentals",
|
|
113
117
|
"nodes.OverseasStockMarketDataNode.description": "Get current price and volume for overseas stocks. (NYSE, NASDAQ, AMEX)",
|
|
114
118
|
"nodes.OverseasStockMarketDataNode.name": "Stock Market Data",
|
|
115
119
|
"nodes.OverseasStockModifyOrderNode.description": "Modify the price or quantity of pending US stock orders.",
|
|
@@ -182,6 +186,9 @@
|
|
|
182
186
|
"fields.AggregateNode.mode": "Select aggregation mode",
|
|
183
187
|
"fields.AggregateNode.value_field": "Field name for calculation (for sum/avg/min/max modes)",
|
|
184
188
|
"fields.AggregateNode.value_field_helper": "Specify a field containing numeric values",
|
|
189
|
+
"fields.IfNode.left": "Left value (comparison target)",
|
|
190
|
+
"fields.IfNode.operator": "Comparison operator",
|
|
191
|
+
"fields.IfNode.right": "Right value (comparison reference)",
|
|
185
192
|
"fields.AlertNode.credential_id": "Alert service credential",
|
|
186
193
|
"fields.AlertNode.message_template": "Message template (variables supported)",
|
|
187
194
|
"fields.BacktestEngineNode.allow_fractional": "Allow fractional shares",
|
|
@@ -337,6 +344,10 @@
|
|
|
337
344
|
"fields.OverseasStockHistoricalDataNode.symbol.exchange": "Exchange",
|
|
338
345
|
"fields.OverseasStockHistoricalDataNode.symbol.help_text": "Direct input or binding available (fx toggle)",
|
|
339
346
|
"fields.OverseasStockHistoricalDataNode.symbol.symbol": "Symbol",
|
|
347
|
+
"fields.OverseasStockFundamentalNode.symbol": "Enter the symbol code for fundamental data lookup",
|
|
348
|
+
"fields.OverseasStockFundamentalNode.symbol.exchange": "Exchange",
|
|
349
|
+
"fields.OverseasStockFundamentalNode.symbol.help_text": "Direct input or binding available (fx toggle)",
|
|
350
|
+
"fields.OverseasStockFundamentalNode.symbol.symbol": "Symbol",
|
|
340
351
|
"fields.OverseasStockMarketDataNode.symbol": "Enter the symbol code for current price lookup",
|
|
341
352
|
"fields.OverseasStockMarketDataNode.symbol.exchange": "Exchange",
|
|
342
353
|
"fields.OverseasStockMarketDataNode.symbol.help_text": "Direct input or binding available (fx toggle)",
|
|
@@ -437,6 +448,9 @@
|
|
|
437
448
|
"fieldNames.AggregateNode.filter_field": "Filter Field",
|
|
438
449
|
"fieldNames.AggregateNode.mode": "Mode",
|
|
439
450
|
"fieldNames.AggregateNode.value_field": "Value Field",
|
|
451
|
+
"fieldNames.IfNode.left": "Left Value",
|
|
452
|
+
"fieldNames.IfNode.operator": "Operator",
|
|
453
|
+
"fieldNames.IfNode.right": "Right Value",
|
|
440
454
|
"fieldNames.BacktestEngineNode.allow_fractional": "Allow Fractional",
|
|
441
455
|
"fieldNames.BacktestEngineNode.allow_short": "Allow Short",
|
|
442
456
|
"fieldNames.BacktestEngineNode.atr_period": "ATR Period",
|
|
@@ -559,6 +573,7 @@
|
|
|
559
573
|
"fieldNames.OverseasStockHistoricalDataNode.interval": "Interval",
|
|
560
574
|
"fieldNames.OverseasStockHistoricalDataNode.start_date": "Start Date",
|
|
561
575
|
"fieldNames.OverseasStockHistoricalDataNode.symbol": "Symbol",
|
|
576
|
+
"fieldNames.OverseasStockFundamentalNode.symbol": "Symbol",
|
|
562
577
|
"fieldNames.OverseasStockMarketDataNode.symbol": "Symbol",
|
|
563
578
|
"fieldNames.OverseasStockModifyOrderNode.exchange": "Exchange",
|
|
564
579
|
"fieldNames.OverseasStockModifyOrderNode.new_price": "New Price",
|
|
@@ -666,6 +681,9 @@
|
|
|
666
681
|
"ports.aggregate_count": "Item count",
|
|
667
682
|
"ports.aggregate_item": "Item to collect",
|
|
668
683
|
"ports.aggregate_value": "Calculated result (sum/avg/min/max)",
|
|
684
|
+
"ports.if_true": "Output when condition is true",
|
|
685
|
+
"ports.if_false": "Output when condition is false",
|
|
686
|
+
"ports.if_result": "Condition evaluation result (boolean)",
|
|
669
687
|
"ports.allocated_capital": "Allocated capital",
|
|
670
688
|
"ports.allocation_weights": "Allocation weights",
|
|
671
689
|
"ports.approved_symbols": "Approved symbols",
|
|
@@ -693,12 +711,15 @@
|
|
|
693
711
|
"ports.current_value": "Current value",
|
|
694
712
|
"ports.data": "Data",
|
|
695
713
|
"ports.data_to_save": "Data to save",
|
|
714
|
+
"ports.deposit": "Deposit",
|
|
696
715
|
"ports.drawdown_curve": "Drawdown curve",
|
|
697
716
|
"ports.equity_curve": "Equity curve",
|
|
717
|
+
"ports.exchange_rate": "Exchange rate",
|
|
698
718
|
"ports.error_data": "Error data",
|
|
699
719
|
"ports.event": "Event data",
|
|
700
720
|
"ports.failed": "Failed",
|
|
701
721
|
"ports.failed_symbols": "Failed symbols",
|
|
722
|
+
"ports.foreign_cash": "Foreign currency cash (USD)",
|
|
702
723
|
"ports.filled": "Order filled",
|
|
703
724
|
"ports.halted": "Halted signal",
|
|
704
725
|
"ports.held_symbols": "Held symbols",
|
|
@@ -715,10 +736,14 @@
|
|
|
715
736
|
"ports.liquidated_positions": "Liquidated positions",
|
|
716
737
|
"ports.liquidation_result": "Liquidation result",
|
|
717
738
|
"ports.loaded_data": "Loaded data",
|
|
739
|
+
"ports.maintenance_margin": "Maintenance margin",
|
|
718
740
|
"ports.mapped_data": "Transformed data",
|
|
719
741
|
"ports.mapped_fields": "Mapped field names list",
|
|
742
|
+
"ports.margin": "Initial margin",
|
|
743
|
+
"ports.margin_call_rate": "Margin call rate (%)",
|
|
720
744
|
"ports.market_data": "Market data",
|
|
721
745
|
"ports.market_data_full": "Full market data",
|
|
746
|
+
"ports.fundamental_data_value": "Fundamental data (PER, EPS, market cap, etc.)",
|
|
722
747
|
"ports.market_data_value": "Market data value",
|
|
723
748
|
"ports.market_data_values": "Market data (price/volume per symbol)",
|
|
724
749
|
"ports.metrics": "Performance metrics",
|
|
@@ -733,6 +758,7 @@
|
|
|
733
758
|
"ports.ohlcv_value": "OHLCV value",
|
|
734
759
|
"ports.open": "Exchange open",
|
|
735
760
|
"ports.open_orders": "Open orders",
|
|
761
|
+
"ports.orderable_amount": "Orderable amount",
|
|
736
762
|
"ports.order": "Order data",
|
|
737
763
|
"ports.order_id": "Order ID",
|
|
738
764
|
"ports.order_ids": "Order IDs per symbol",
|
|
@@ -763,6 +789,7 @@
|
|
|
763
789
|
"ports.resume_at": "Resume time",
|
|
764
790
|
"ports.saved_data": "Saved data",
|
|
765
791
|
"ports.sell_signal": "Sell signal",
|
|
792
|
+
"ports.settlement_pnl": "Settlement P&L",
|
|
766
793
|
"ports.signals": "Signal data",
|
|
767
794
|
"ports.split_array": "Array to split",
|
|
768
795
|
"ports.split_index": "Current index (0-based)",
|
|
@@ -785,6 +812,8 @@
|
|
|
785
812
|
"ports.target_orders": "Target orders",
|
|
786
813
|
"ports.throttle_stats": "Throttle stats (skip count, countdown, etc.)",
|
|
787
814
|
"ports.tick_data": "Tick data",
|
|
815
|
+
"ports.total_eval": "Total evaluation amount",
|
|
816
|
+
"ports.total_orderable": "Total orderable amount",
|
|
788
817
|
"ports.total_pnl": "Total P&L",
|
|
789
818
|
"ports.trades": "Trades",
|
|
790
819
|
"ports.trigger": "Trigger signal",
|
|
@@ -800,6 +829,18 @@
|
|
|
800
829
|
"enums.aggregate_mode.max": "Maximum",
|
|
801
830
|
"enums.aggregate_mode.min": "Minimum",
|
|
802
831
|
"enums.aggregate_mode.sum": "Sum",
|
|
832
|
+
"enums.if_operator.eq": "Equals (==)",
|
|
833
|
+
"enums.if_operator.ne": "Not equals (!=)",
|
|
834
|
+
"enums.if_operator.gt": "Greater than (>)",
|
|
835
|
+
"enums.if_operator.gte": "Greater or equal (>=)",
|
|
836
|
+
"enums.if_operator.lt": "Less than (<)",
|
|
837
|
+
"enums.if_operator.lte": "Less or equal (<=)",
|
|
838
|
+
"enums.if_operator.in": "Is in (in)",
|
|
839
|
+
"enums.if_operator.not_in": "Is not in (not in)",
|
|
840
|
+
"enums.if_operator.contains": "Contains",
|
|
841
|
+
"enums.if_operator.not_contains": "Does not contain",
|
|
842
|
+
"enums.if_operator.is_empty": "Is empty",
|
|
843
|
+
"enums.if_operator.is_not_empty": "Is not empty",
|
|
803
844
|
"enums.allocation_method.custom": "Custom Allocation",
|
|
804
845
|
"enums.allocation_method.equal": "Equal Weight",
|
|
805
846
|
"enums.allocation_method.momentum": "Momentum Based",
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/i18n/locales/ko.json
RENAMED
|
@@ -36,6 +36,8 @@
|
|
|
36
36
|
"nodes.AIAgentNode.name": "AI 에이전트",
|
|
37
37
|
"nodes.AggregateNode.description": "개별 아이템을 리스트로 수집합니다. SplitNode와 함께 사용하세요.",
|
|
38
38
|
"nodes.AggregateNode.name": "집계",
|
|
39
|
+
"nodes.IfNode.description": "조건에 따라 실행 흐름을 분기합니다 (if/else)",
|
|
40
|
+
"nodes.IfNode.name": "조건 분기",
|
|
39
41
|
"nodes.AlertNode.description": "알림 발송 (이메일, SMS, 웹훅).",
|
|
40
42
|
"nodes.AlertNode.name": "알림",
|
|
41
43
|
"nodes.BacktestEngineNode.description": "시그널과 과거 데이터로 백테스트 실행 및 성과 지표 계산.",
|
|
@@ -110,6 +112,8 @@
|
|
|
110
112
|
"nodes.OverseasStockCancelOrderNode.name": "해외주식 취소주문",
|
|
111
113
|
"nodes.OverseasStockHistoricalDataNode.description": "해외주식 종목의 과거 OHLCV 데이터를 조회합니다. (NYSE, NASDAQ, AMEX)",
|
|
112
114
|
"nodes.OverseasStockHistoricalDataNode.name": "해외주식 과거데이터",
|
|
115
|
+
"nodes.OverseasStockFundamentalNode.description": "해외주식 종목의 PER, EPS, 시가총액, 52주 고/저가 등 펀더멘털 데이터를 조회합니다. (NYSE, NASDAQ, AMEX)",
|
|
116
|
+
"nodes.OverseasStockFundamentalNode.name": "해외주식 종목정보",
|
|
113
117
|
"nodes.OverseasStockMarketDataNode.description": "해외주식 종목의 현재가와 거래량을 조회합니다. (NYSE, NASDAQ, AMEX)",
|
|
114
118
|
"nodes.OverseasStockMarketDataNode.name": "해외주식 현재가",
|
|
115
119
|
"nodes.OverseasStockModifyOrderNode.description": "미국 주식 미체결 주문의 가격이나 수량을 정정합니다.",
|
|
@@ -182,6 +186,9 @@
|
|
|
182
186
|
"fields.AggregateNode.mode": "집계 방식을 선택하세요",
|
|
183
187
|
"fields.AggregateNode.value_field": "계산에 사용할 필드명 (sum/avg/min/max 모드용)",
|
|
184
188
|
"fields.AggregateNode.value_field_helper": "숫자 값이 있는 필드를 지정하세요",
|
|
189
|
+
"fields.IfNode.left": "왼쪽 값 (비교 대상)",
|
|
190
|
+
"fields.IfNode.operator": "비교 연산자",
|
|
191
|
+
"fields.IfNode.right": "오른쪽 값 (비교 기준)",
|
|
185
192
|
"fields.AlertNode.credential_id": "알림 서비스 인증정보",
|
|
186
193
|
"fields.AlertNode.message_template": "메시지 템플릿 (변수 사용 가능)",
|
|
187
194
|
"fields.BacktestEngineNode.allow_fractional": "소수점 주식 허용",
|
|
@@ -337,6 +344,10 @@
|
|
|
337
344
|
"fields.OverseasStockHistoricalDataNode.symbol.exchange": "거래소",
|
|
338
345
|
"fields.OverseasStockHistoricalDataNode.symbol.help_text": "직접 입력 또는 바인딩 가능 (fx 토글)",
|
|
339
346
|
"fields.OverseasStockHistoricalDataNode.symbol.symbol": "종목코드",
|
|
347
|
+
"fields.OverseasStockFundamentalNode.symbol": "펀더멘털 데이터를 조회할 종목 코드를 입력하세요",
|
|
348
|
+
"fields.OverseasStockFundamentalNode.symbol.exchange": "거래소",
|
|
349
|
+
"fields.OverseasStockFundamentalNode.symbol.help_text": "직접 입력 또는 바인딩 가능 (fx 토글)",
|
|
350
|
+
"fields.OverseasStockFundamentalNode.symbol.symbol": "종목코드",
|
|
340
351
|
"fields.OverseasStockMarketDataNode.symbol": "현재가를 조회할 종목 코드를 입력하세요",
|
|
341
352
|
"fields.OverseasStockMarketDataNode.symbol.exchange": "거래소",
|
|
342
353
|
"fields.OverseasStockMarketDataNode.symbol.help_text": "직접 입력 또는 바인딩 가능 (fx 토글)",
|
|
@@ -437,6 +448,9 @@
|
|
|
437
448
|
"fieldNames.AggregateNode.filter_field": "필터필드",
|
|
438
449
|
"fieldNames.AggregateNode.mode": "집계방식",
|
|
439
450
|
"fieldNames.AggregateNode.value_field": "값필드",
|
|
451
|
+
"fieldNames.IfNode.left": "왼쪽 값",
|
|
452
|
+
"fieldNames.IfNode.operator": "연산자",
|
|
453
|
+
"fieldNames.IfNode.right": "오른쪽 값",
|
|
440
454
|
"fieldNames.BacktestEngineNode.allow_fractional": "소수점매매허용",
|
|
441
455
|
"fieldNames.BacktestEngineNode.allow_short": "공매도허용",
|
|
442
456
|
"fieldNames.BacktestEngineNode.atr_period": "ATR기간",
|
|
@@ -559,6 +573,7 @@
|
|
|
559
573
|
"fieldNames.OverseasStockHistoricalDataNode.interval": "봉종류",
|
|
560
574
|
"fieldNames.OverseasStockHistoricalDataNode.start_date": "시작일",
|
|
561
575
|
"fieldNames.OverseasStockHistoricalDataNode.symbol": "종목",
|
|
576
|
+
"fieldNames.OverseasStockFundamentalNode.symbol": "종목",
|
|
562
577
|
"fieldNames.OverseasStockMarketDataNode.symbol": "종목",
|
|
563
578
|
"fieldNames.OverseasStockModifyOrderNode.exchange": "거래소",
|
|
564
579
|
"fieldNames.OverseasStockModifyOrderNode.new_price": "정정가격",
|
|
@@ -666,6 +681,9 @@
|
|
|
666
681
|
"ports.aggregate_count": "아이템 개수",
|
|
667
682
|
"ports.aggregate_item": "수집할 아이템",
|
|
668
683
|
"ports.aggregate_value": "계산 결과 (sum/avg/min/max)",
|
|
684
|
+
"ports.if_true": "조건이 참일 때 출력",
|
|
685
|
+
"ports.if_false": "조건이 거짓일 때 출력",
|
|
686
|
+
"ports.if_result": "조건 평가 결과 (boolean)",
|
|
669
687
|
"ports.allocated_capital": "배분된 자본",
|
|
670
688
|
"ports.allocation_weights": "배분 비중",
|
|
671
689
|
"ports.approved_symbols": "승인된 종목",
|
|
@@ -693,12 +711,15 @@
|
|
|
693
711
|
"ports.current_value": "현재 값",
|
|
694
712
|
"ports.data": "데이터",
|
|
695
713
|
"ports.data_to_save": "저장할 데이터",
|
|
714
|
+
"ports.deposit": "예수금",
|
|
696
715
|
"ports.drawdown_curve": "낙폭 곡선",
|
|
697
716
|
"ports.equity_curve": "자산 곡선",
|
|
717
|
+
"ports.exchange_rate": "기준환율",
|
|
698
718
|
"ports.error_data": "에러 데이터",
|
|
699
719
|
"ports.event": "이벤트 데이터",
|
|
700
720
|
"ports.failed": "실패",
|
|
701
721
|
"ports.failed_symbols": "미통과 종목",
|
|
722
|
+
"ports.foreign_cash": "외화예수금 (USD)",
|
|
702
723
|
"ports.filled": "체결됨",
|
|
703
724
|
"ports.halted": "중단 신호",
|
|
704
725
|
"ports.held_symbols": "보유 종목",
|
|
@@ -715,10 +736,14 @@
|
|
|
715
736
|
"ports.liquidated_positions": "청산된 포지션",
|
|
716
737
|
"ports.liquidation_result": "청산 결과",
|
|
717
738
|
"ports.loaded_data": "로드된 데이터",
|
|
739
|
+
"ports.maintenance_margin": "유지증거금",
|
|
718
740
|
"ports.mapped_data": "변환된 데이터",
|
|
719
741
|
"ports.mapped_fields": "매핑된 필드명 목록",
|
|
742
|
+
"ports.margin": "위탁증거금",
|
|
743
|
+
"ports.margin_call_rate": "마진콜율 (%)",
|
|
720
744
|
"ports.market_data": "시세 데이터",
|
|
721
745
|
"ports.market_data_full": "전체 시세 데이터",
|
|
746
|
+
"ports.fundamental_data_value": "펀더멘털 데이터 (PER, EPS, 시가총액 등)",
|
|
722
747
|
"ports.market_data_value": "시세 값",
|
|
723
748
|
"ports.market_data_values": "시세 데이터 (종목별 가격/거래량)",
|
|
724
749
|
"ports.metrics": "성과 지표",
|
|
@@ -733,6 +758,7 @@
|
|
|
733
758
|
"ports.ohlcv_value": "OHLCV 값",
|
|
734
759
|
"ports.open": "거래소 개장",
|
|
735
760
|
"ports.open_orders": "미체결 주문",
|
|
761
|
+
"ports.orderable_amount": "주문가능금액",
|
|
736
762
|
"ports.order": "주문 데이터",
|
|
737
763
|
"ports.order_id": "주문 번호",
|
|
738
764
|
"ports.order_ids": "종목별 주문번호",
|
|
@@ -763,6 +789,7 @@
|
|
|
763
789
|
"ports.resume_at": "재개 시간",
|
|
764
790
|
"ports.saved_data": "저장된 데이터",
|
|
765
791
|
"ports.sell_signal": "매도 시그널",
|
|
792
|
+
"ports.settlement_pnl": "청산손익",
|
|
766
793
|
"ports.signals": "시그널 데이터",
|
|
767
794
|
"ports.split_array": "분리할 리스트",
|
|
768
795
|
"ports.split_index": "현재 인덱스 (0부터)",
|
|
@@ -785,6 +812,8 @@
|
|
|
785
812
|
"ports.target_orders": "대상 주문",
|
|
786
813
|
"ports.throttle_stats": "쓰로틀 통계 (스킵 횟수, 카운트다운 등)",
|
|
787
814
|
"ports.tick_data": "틱 데이터",
|
|
815
|
+
"ports.total_eval": "평가예탁총금액",
|
|
816
|
+
"ports.total_orderable": "전체 주문가능금액 합산",
|
|
788
817
|
"ports.total_pnl": "총 손익",
|
|
789
818
|
"ports.trades": "거래 내역",
|
|
790
819
|
"ports.trigger": "트리거 신호",
|
|
@@ -800,6 +829,18 @@
|
|
|
800
829
|
"enums.aggregate_mode.max": "최댓값",
|
|
801
830
|
"enums.aggregate_mode.min": "최솟값",
|
|
802
831
|
"enums.aggregate_mode.sum": "합계",
|
|
832
|
+
"enums.if_operator.eq": "같음 (==)",
|
|
833
|
+
"enums.if_operator.ne": "다름 (!=)",
|
|
834
|
+
"enums.if_operator.gt": "초과 (>)",
|
|
835
|
+
"enums.if_operator.gte": "이상 (>=)",
|
|
836
|
+
"enums.if_operator.lt": "미만 (<)",
|
|
837
|
+
"enums.if_operator.lte": "이하 (<=)",
|
|
838
|
+
"enums.if_operator.in": "포함됨 (in)",
|
|
839
|
+
"enums.if_operator.not_in": "미포함됨 (not in)",
|
|
840
|
+
"enums.if_operator.contains": "포함함 (contains)",
|
|
841
|
+
"enums.if_operator.not_contains": "미포함함 (not contains)",
|
|
842
|
+
"enums.if_operator.is_empty": "비어있음",
|
|
843
|
+
"enums.if_operator.is_not_empty": "비어있지 않음",
|
|
803
844
|
"enums.allocation_method.custom": "커스텀 배분",
|
|
804
845
|
"enums.allocation_method.equal": "균등 배분",
|
|
805
846
|
"enums.allocation_method.momentum": "모멘텀 기반",
|
|
@@ -58,6 +58,10 @@ class Edge(BaseModel):
|
|
|
58
58
|
alias="to",
|
|
59
59
|
description="도착 노드 ID",
|
|
60
60
|
)
|
|
61
|
+
from_port: Optional[str] = Field(
|
|
62
|
+
default=None,
|
|
63
|
+
description="출발 포트 (예: IfNode의 true/false)",
|
|
64
|
+
)
|
|
61
65
|
edge_type: EdgeType = Field(
|
|
62
66
|
default=EdgeType.MAIN,
|
|
63
67
|
alias="type",
|
|
@@ -78,20 +82,27 @@ class Edge(BaseModel):
|
|
|
78
82
|
@classmethod
|
|
79
83
|
def extract_node_ids(cls, values: dict) -> dict:
|
|
80
84
|
"""
|
|
81
|
-
from/to 값에서 노드 ID만
|
|
82
|
-
|
|
83
|
-
"nodeA.portX" → "nodeA"
|
|
84
|
-
"nodeA" → "nodeA"
|
|
85
|
+
from/to 값에서 노드 ID만 추출하고 포트 정보를 보존
|
|
86
|
+
|
|
87
|
+
"nodeA.portX" → from="nodeA", from_port="portX"
|
|
88
|
+
"nodeA" → from="nodeA"
|
|
85
89
|
"""
|
|
86
90
|
if isinstance(values, dict):
|
|
87
91
|
from_val = values.get('from') or values.get('from_node')
|
|
88
92
|
to_val = values.get('to') or values.get('to_node')
|
|
89
|
-
|
|
93
|
+
|
|
90
94
|
if from_val:
|
|
91
|
-
|
|
95
|
+
from_str = str(from_val)
|
|
96
|
+
if '.' in from_str:
|
|
97
|
+
parts = from_str.split('.', 1)
|
|
98
|
+
values['from'] = parts[0]
|
|
99
|
+
if not values.get('from_port'):
|
|
100
|
+
values['from_port'] = parts[1]
|
|
101
|
+
else:
|
|
102
|
+
values['from'] = from_str
|
|
92
103
|
if to_val:
|
|
93
|
-
values['to'] = to_val.split('.')[0]
|
|
94
|
-
|
|
104
|
+
values['to'] = str(to_val).split('.')[0]
|
|
105
|
+
|
|
95
106
|
return values
|
|
96
107
|
|
|
97
108
|
# 하위호환성을 위한 property (기존 코드가 참조하는 경우)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"""
|
|
2
2
|
ProgramGarden Core - 노드 타입 정의
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
- infra (
|
|
4
|
+
49개 노드 타입을 카테고리로 분류:
|
|
5
|
+
- infra (5): StartNode, ThrottleNode, SplitNode, AggregateNode, IfNode
|
|
6
6
|
- broker (2): OverseasStockBrokerNode, OverseasFuturesBrokerNode
|
|
7
|
-
- market (
|
|
7
|
+
- market (13): OverseasStockMarketDataNode, OverseasStockFundamentalNode, OverseasFuturesMarketDataNode, OverseasStockHistoricalDataNode, OverseasFuturesHistoricalDataNode,
|
|
8
8
|
OverseasStockRealMarketDataNode, OverseasFuturesRealMarketDataNode, OverseasStockSymbolQueryNode, OverseasFuturesSymbolQueryNode,
|
|
9
9
|
WatchlistNode, MarketUniverseNode, ScreenerNode, SymbolFilterNode
|
|
10
10
|
- account (6): OverseasStockAccountNode, OverseasFuturesAccountNode, OverseasStockRealAccountNode, OverseasFuturesRealAccountNode,
|
|
@@ -22,10 +22,11 @@ ProgramGarden Core - 노드 타입 정의
|
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
24
|
from programgarden_core.nodes.base import BaseNode, NodeCategory, Position
|
|
25
|
-
from programgarden_core.nodes.infra import StartNode, ThrottleNode, SplitNode, AggregateNode
|
|
25
|
+
from programgarden_core.nodes.infra import StartNode, ThrottleNode, SplitNode, AggregateNode, IfNode
|
|
26
26
|
from programgarden_core.nodes.broker import OverseasStockBrokerNode, OverseasFuturesBrokerNode
|
|
27
27
|
# Market - 상품별 분리 노드
|
|
28
28
|
from programgarden_core.nodes.data_stock import OverseasStockMarketDataNode
|
|
29
|
+
from programgarden_core.nodes.fundamental_stock import OverseasStockFundamentalNode
|
|
29
30
|
from programgarden_core.nodes.data_futures import OverseasFuturesMarketDataNode
|
|
30
31
|
from programgarden_core.nodes.backtest_stock import OverseasStockHistoricalDataNode
|
|
31
32
|
from programgarden_core.nodes.backtest_futures import OverseasFuturesHistoricalDataNode
|
|
@@ -95,11 +96,13 @@ __all__ = [
|
|
|
95
96
|
"ThrottleNode",
|
|
96
97
|
"SplitNode",
|
|
97
98
|
"AggregateNode",
|
|
99
|
+
"IfNode",
|
|
98
100
|
# Broker (상품별 분리)
|
|
99
101
|
"OverseasStockBrokerNode",
|
|
100
102
|
"OverseasFuturesBrokerNode",
|
|
101
103
|
# Market - Stock (해외주식)
|
|
102
104
|
"OverseasStockMarketDataNode",
|
|
105
|
+
"OverseasStockFundamentalNode",
|
|
103
106
|
"OverseasStockHistoricalDataNode",
|
|
104
107
|
"OverseasStockRealMarketDataNode",
|
|
105
108
|
"OverseasStockSymbolQueryNode",
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/account_futures.py
RENAMED
|
@@ -18,7 +18,7 @@ from programgarden_core.nodes.base import (
|
|
|
18
18
|
OutputPort,
|
|
19
19
|
ProductScope,
|
|
20
20
|
BrokerProvider,
|
|
21
|
-
|
|
21
|
+
OVERSEAS_FUTURES_BALANCE_FIELDS,
|
|
22
22
|
POSITION_FIELDS,
|
|
23
23
|
SYMBOL_LIST_FIELDS,
|
|
24
24
|
)
|
|
@@ -53,7 +53,7 @@ class OverseasFuturesAccountNode(BaseNode):
|
|
|
53
53
|
]
|
|
54
54
|
_outputs: List[OutputPort] = [
|
|
55
55
|
OutputPort(name="held_symbols", type="symbol_list", description="i18n:ports.held_symbols", fields=SYMBOL_LIST_FIELDS),
|
|
56
|
-
OutputPort(name="balance", type="balance_data", description="i18n:ports.balance", fields=
|
|
56
|
+
OutputPort(name="balance", type="balance_data", description="i18n:ports.balance", fields=OVERSEAS_FUTURES_BALANCE_FIELDS),
|
|
57
57
|
OutputPort(name="positions", type="position_data", description="i18n:ports.positions", fields=POSITION_FIELDS),
|
|
58
58
|
]
|
|
59
59
|
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/account_stock.py
RENAMED
|
@@ -18,7 +18,7 @@ from programgarden_core.nodes.base import (
|
|
|
18
18
|
OutputPort,
|
|
19
19
|
ProductScope,
|
|
20
20
|
BrokerProvider,
|
|
21
|
-
|
|
21
|
+
OVERSEAS_STOCK_BALANCE_FIELDS,
|
|
22
22
|
POSITION_FIELDS,
|
|
23
23
|
SYMBOL_LIST_FIELDS,
|
|
24
24
|
)
|
|
@@ -53,7 +53,7 @@ class OverseasStockAccountNode(BaseNode):
|
|
|
53
53
|
]
|
|
54
54
|
_outputs: List[OutputPort] = [
|
|
55
55
|
OutputPort(name="held_symbols", type="symbol_list", description="i18n:ports.held_symbols", fields=SYMBOL_LIST_FIELDS),
|
|
56
|
-
OutputPort(name="balance", type="balance_data", description="i18n:ports.balance", fields=
|
|
56
|
+
OutputPort(name="balance", type="balance_data", description="i18n:ports.balance", fields=OVERSEAS_STOCK_BALANCE_FIELDS),
|
|
57
57
|
OutputPort(name="positions", type="position_data", description="i18n:ports.positions", fields=POSITION_FIELDS),
|
|
58
58
|
]
|
|
59
59
|
|
|
@@ -100,7 +100,7 @@ class LLMModelNode(BaseNode):
|
|
|
100
100
|
category=FieldCategory.PARAMETERS,
|
|
101
101
|
expression_mode=ExpressionMode.FIXED_ONLY,
|
|
102
102
|
ui_component=UIComponent.CUSTOM_CREDENTIAL_SELECT,
|
|
103
|
-
credential_types=["llm_openai", "llm_anthropic", "llm_google"
|
|
103
|
+
credential_types=["llm_openai", "llm_anthropic", "llm_google"],
|
|
104
104
|
),
|
|
105
105
|
"model": FieldSchema(
|
|
106
106
|
name="model",
|
|
@@ -112,7 +112,39 @@ SYMBOL_LIST_FIELDS: List[Dict[str, str]] = [
|
|
|
112
112
|
{"name": "symbol", "type": "string", "description": "종목코드"},
|
|
113
113
|
]
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
# ── 해외주식 REST AccountNode 전용 ──
|
|
116
|
+
OVERSEAS_STOCK_BALANCE_FIELDS: List[Dict[str, str]] = [
|
|
117
|
+
{"name": "total_pnl_rate", "type": "number", "description": "수익률 (%)"},
|
|
118
|
+
{"name": "cash_krw", "type": "number", "description": "원화예수금"},
|
|
119
|
+
{"name": "stock_eval_krw", "type": "number", "description": "주식환산평가금액"},
|
|
120
|
+
{"name": "total_eval_krw", "type": "number", "description": "원화평가합계"},
|
|
121
|
+
{"name": "total_pnl_krw", "type": "number", "description": "환산평가손익"},
|
|
122
|
+
{"name": "orderable_amount", "type": "number", "description": "외화주문가능금액 (USD)"},
|
|
123
|
+
{"name": "foreign_cash", "type": "number", "description": "외화예수금 (USD)"},
|
|
124
|
+
{"name": "exchange_rate", "type": "number", "description": "기준환율"},
|
|
125
|
+
]
|
|
126
|
+
|
|
127
|
+
# ── 해외선물 REST AccountNode 전용 ──
|
|
128
|
+
OVERSEAS_FUTURES_BALANCE_FIELDS: List[Dict[str, str]] = [
|
|
129
|
+
{"name": "deposit", "type": "number", "description": "예수금"},
|
|
130
|
+
{"name": "orderable_amount", "type": "number", "description": "주문가능금액"},
|
|
131
|
+
{"name": "total_orderable", "type": "number", "description": "전체 주문가능금액 합산"},
|
|
132
|
+
{"name": "margin", "type": "number", "description": "위탁증거금"},
|
|
133
|
+
{"name": "maintenance_margin", "type": "number", "description": "유지증거금"},
|
|
134
|
+
{"name": "margin_call_rate", "type": "number", "description": "마진콜율 (%)"},
|
|
135
|
+
{"name": "total_eval", "type": "number", "description": "평가예탁총금액"},
|
|
136
|
+
{"name": "settlement_pnl", "type": "number", "description": "청산손익"},
|
|
137
|
+
]
|
|
138
|
+
|
|
139
|
+
# ── 해외주식 RealAccountNode 전용 ──
|
|
140
|
+
OVERSEAS_STOCK_REAL_BALANCE_FIELDS: List[Dict[str, str]] = [
|
|
141
|
+
{"name": "total", "type": "number", "description": "총 예수금"},
|
|
142
|
+
{"name": "available", "type": "number", "description": "매수 가능 금액"},
|
|
143
|
+
{"name": "currency", "type": "string", "description": "통화 코드 (USD 등)"},
|
|
144
|
+
]
|
|
145
|
+
|
|
146
|
+
# ── 해외선물 RealAccountNode 전용 ──
|
|
147
|
+
OVERSEAS_FUTURES_REAL_BALANCE_FIELDS: List[Dict[str, str]] = [
|
|
116
148
|
{"name": "total", "type": "number", "description": "총 예수금"},
|
|
117
149
|
{"name": "available", "type": "number", "description": "매수 가능 금액"},
|
|
118
150
|
{"name": "currency", "type": "string", "description": "통화 코드 (USD 등)"},
|
|
@@ -144,6 +176,27 @@ PRICE_DATA_FIELDS: List[Dict[str, str]] = [
|
|
|
144
176
|
{"name": "current_price", "type": "number", "description": "현재가"},
|
|
145
177
|
{"name": "volume", "type": "number", "description": "거래량"},
|
|
146
178
|
{"name": "change_percent", "type": "number", "description": "등락률 (%)"},
|
|
179
|
+
{"name": "per", "type": "number", "description": "PER (주가수익비율)"},
|
|
180
|
+
{"name": "eps", "type": "number", "description": "EPS (주당순이익)"},
|
|
181
|
+
]
|
|
182
|
+
|
|
183
|
+
FUNDAMENTAL_DATA_FIELDS: List[Dict[str, str]] = [
|
|
184
|
+
{"name": "exchange", "type": "string", "description": "거래소 코드"},
|
|
185
|
+
{"name": "symbol", "type": "string", "description": "종목코드"},
|
|
186
|
+
{"name": "name", "type": "string", "description": "영문 종목명"},
|
|
187
|
+
{"name": "industry", "type": "string", "description": "업종명"},
|
|
188
|
+
{"name": "nation", "type": "string", "description": "국가명"},
|
|
189
|
+
{"name": "exchange_name", "type": "string", "description": "거래소명"},
|
|
190
|
+
{"name": "current_price", "type": "number", "description": "현재가"},
|
|
191
|
+
{"name": "volume", "type": "number", "description": "거래량"},
|
|
192
|
+
{"name": "change_percent", "type": "number", "description": "등락률 (%)"},
|
|
193
|
+
{"name": "per", "type": "number", "description": "PER (주가수익비율)"},
|
|
194
|
+
{"name": "eps", "type": "number", "description": "EPS (주당순이익)"},
|
|
195
|
+
{"name": "market_cap", "type": "number", "description": "시가총액"},
|
|
196
|
+
{"name": "shares_outstanding", "type": "number", "description": "발행주식수"},
|
|
197
|
+
{"name": "high_52w", "type": "number", "description": "52주 최고가"},
|
|
198
|
+
{"name": "low_52w", "type": "number", "description": "52주 최저가"},
|
|
199
|
+
{"name": "exchange_rate", "type": "number", "description": "환율"},
|
|
147
200
|
]
|
|
148
201
|
|
|
149
202
|
HISTORICAL_DATA_FIELDS: List[Dict[str, str]] = [
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ProgramGarden Core - Stock Fundamental Node
|
|
3
|
+
|
|
4
|
+
해외주식 종목정보(펀더멘털) 조회:
|
|
5
|
+
- OverseasStockFundamentalNode: g3104 API 기반 종목정보 조회
|
|
6
|
+
|
|
7
|
+
Item-based execution:
|
|
8
|
+
- Input: 단일 symbol (SplitNode에서 분리된 아이템)
|
|
9
|
+
- Output: 단일 value (해당 종목의 펀더멘털 데이터)
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from typing import List, Literal, Dict, ClassVar, Optional, TYPE_CHECKING
|
|
13
|
+
from pydantic import Field
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from programgarden_core.models.field_binding import FieldSchema
|
|
17
|
+
|
|
18
|
+
from programgarden_core.nodes.base import (
|
|
19
|
+
BaseNode,
|
|
20
|
+
NodeCategory,
|
|
21
|
+
InputPort,
|
|
22
|
+
OutputPort,
|
|
23
|
+
ProductScope,
|
|
24
|
+
BrokerProvider,
|
|
25
|
+
FUNDAMENTAL_DATA_FIELDS,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class OverseasStockFundamentalNode(BaseNode):
|
|
30
|
+
"""
|
|
31
|
+
해외주식 종목정보(펀더멘털) 조회 노드 (단일 종목)
|
|
32
|
+
|
|
33
|
+
PER, EPS, 시가총액, 발행주식수, 52주 고/저가, 업종 등
|
|
34
|
+
종목의 기본적 분석 데이터를 조회합니다.
|
|
35
|
+
거래소: NYSE, NASDAQ, AMEX
|
|
36
|
+
|
|
37
|
+
Item-based execution:
|
|
38
|
+
- Input: symbol (단일 종목 {exchange, symbol})
|
|
39
|
+
- Output: value (해당 종목의 펀더멘털 데이터)
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
type: Literal["OverseasStockFundamentalNode"] = "OverseasStockFundamentalNode"
|
|
43
|
+
category: NodeCategory = NodeCategory.MARKET
|
|
44
|
+
description: str = "i18n:nodes.OverseasStockFundamentalNode.description"
|
|
45
|
+
_img_url: ClassVar[str] = "https://cdn.programgarden.io/nodes/fundamental_stock.svg"
|
|
46
|
+
_product_scope: ClassVar[ProductScope] = ProductScope.STOCK
|
|
47
|
+
_broker_provider: ClassVar[BrokerProvider] = BrokerProvider.LS
|
|
48
|
+
|
|
49
|
+
# 단일 종목 (Item-based execution)
|
|
50
|
+
symbol: Optional[Dict[str, str]] = Field(
|
|
51
|
+
default=None,
|
|
52
|
+
description="Single symbol entry with exchange and symbol code",
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
@classmethod
|
|
56
|
+
def is_tool_enabled(cls) -> bool:
|
|
57
|
+
return True
|
|
58
|
+
|
|
59
|
+
_inputs: List[InputPort] = [
|
|
60
|
+
InputPort(name="symbol", type="symbol", description="i18n:ports.symbol"),
|
|
61
|
+
InputPort(name="trigger", type="signal", description="i18n:ports.trigger", required=False),
|
|
62
|
+
]
|
|
63
|
+
_outputs: List[OutputPort] = [
|
|
64
|
+
OutputPort(name="value", type="fundamental_data", description="i18n:ports.fundamental_data_value", fields=FUNDAMENTAL_DATA_FIELDS),
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
@classmethod
|
|
68
|
+
def get_field_schema(cls) -> Dict[str, "FieldSchema"]:
|
|
69
|
+
from programgarden_core.models.field_binding import FieldSchema, FieldType, FieldCategory, UIComponent, ExpressionMode
|
|
70
|
+
return {
|
|
71
|
+
"symbol": FieldSchema(
|
|
72
|
+
name="symbol",
|
|
73
|
+
type=FieldType.OBJECT,
|
|
74
|
+
display_name="i18n:fieldNames.OverseasStockFundamentalNode.symbol",
|
|
75
|
+
description="i18n:fields.OverseasStockFundamentalNode.symbol",
|
|
76
|
+
default=None,
|
|
77
|
+
category=FieldCategory.PARAMETERS,
|
|
78
|
+
expression_mode=ExpressionMode.EXPRESSION_ONLY,
|
|
79
|
+
example={"exchange": "NASDAQ", "symbol": "AAPL"},
|
|
80
|
+
example_binding="{{ nodes.split.item }}",
|
|
81
|
+
bindable_sources=[
|
|
82
|
+
"SplitNode.item",
|
|
83
|
+
],
|
|
84
|
+
expected_type="{exchange: str, symbol: str}",
|
|
85
|
+
help_text="i18n:fields.OverseasStockFundamentalNode.symbol.help_text",
|
|
86
|
+
object_schema=[
|
|
87
|
+
{"name": "exchange", "type": "STRING", "label": "i18n:fields.OverseasStockFundamentalNode.symbol.exchange", "required": True},
|
|
88
|
+
{"name": "symbol", "type": "STRING", "label": "i18n:fields.OverseasStockFundamentalNode.symbol.symbol", "required": True},
|
|
89
|
+
],
|
|
90
|
+
),
|
|
91
|
+
}
|
|
@@ -6,6 +6,7 @@ Infrastructure nodes:
|
|
|
6
6
|
- ThrottleNode: Data flow control
|
|
7
7
|
- SplitNode: Split list into individual items (item-based execution)
|
|
8
8
|
- AggregateNode: Aggregate individual items into a list
|
|
9
|
+
- IfNode: Conditional branching (if/else)
|
|
9
10
|
"""
|
|
10
11
|
|
|
11
12
|
from typing import Optional, List, Literal, Dict, TYPE_CHECKING, ClassVar, Any
|
|
@@ -309,3 +310,106 @@ class AggregateNode(BaseNode):
|
|
|
309
310
|
helper_text="i18n:fields.AggregateNode.value_field_helper",
|
|
310
311
|
),
|
|
311
312
|
}
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
class IfNode(BaseNode):
|
|
316
|
+
"""
|
|
317
|
+
조건 분기 노드
|
|
318
|
+
|
|
319
|
+
left와 right 값을 operator로 비교하여 true/false 브랜치로 실행 흐름을 분기합니다.
|
|
320
|
+
조건이 참이면 true 포트로, 거짓이면 false 포트로 데이터가 전달됩니다.
|
|
321
|
+
|
|
322
|
+
Edge에 from_port를 지정하여 분기 경로를 설정합니다:
|
|
323
|
+
- {"from": "if1", "to": "order", "from_port": "true"}
|
|
324
|
+
- {"from": "if1", "to": "notify", "from_port": "false"}
|
|
325
|
+
"""
|
|
326
|
+
|
|
327
|
+
type: Literal["IfNode"] = "IfNode"
|
|
328
|
+
category: NodeCategory = NodeCategory.INFRA
|
|
329
|
+
description: str = "i18n:nodes.IfNode.description"
|
|
330
|
+
|
|
331
|
+
_img_url: ClassVar[str] = "https://cdn.programgarden.io/nodes/if.svg"
|
|
332
|
+
|
|
333
|
+
# 비교 연산 필드
|
|
334
|
+
left: Any = Field(default=None, description="왼쪽 피연산자 (표현식 바인딩 가능)")
|
|
335
|
+
operator: Literal[
|
|
336
|
+
"==", "!=", ">", ">=", "<", "<=",
|
|
337
|
+
"in", "not_in",
|
|
338
|
+
"contains", "not_contains",
|
|
339
|
+
"is_empty", "is_not_empty",
|
|
340
|
+
] = Field(default="==", description="비교 연산자")
|
|
341
|
+
right: Any = Field(default=None, description="오른쪽 피연산자 (표현식 바인딩 가능)")
|
|
342
|
+
|
|
343
|
+
_inputs: List[InputPort] = [
|
|
344
|
+
InputPort(name="trigger", type="signal", description="i18n:ports.trigger"),
|
|
345
|
+
]
|
|
346
|
+
_outputs: List[OutputPort] = [
|
|
347
|
+
OutputPort(name="true", type="any", description="i18n:ports.if_true"),
|
|
348
|
+
OutputPort(name="false", type="any", description="i18n:ports.if_false"),
|
|
349
|
+
OutputPort(name="result", type="boolean", description="i18n:ports.if_result"),
|
|
350
|
+
]
|
|
351
|
+
|
|
352
|
+
@classmethod
|
|
353
|
+
def get_field_schema(cls) -> Dict[str, "FieldSchema"]:
|
|
354
|
+
from programgarden_core.models.field_binding import (
|
|
355
|
+
FieldSchema, FieldType, FieldCategory, ExpressionMode,
|
|
356
|
+
)
|
|
357
|
+
return {
|
|
358
|
+
"left": FieldSchema(
|
|
359
|
+
name="left",
|
|
360
|
+
type=FieldType.STRING,
|
|
361
|
+
description="i18n:fields.IfNode.left",
|
|
362
|
+
required=True,
|
|
363
|
+
expression_mode=ExpressionMode.BOTH,
|
|
364
|
+
category=FieldCategory.PARAMETERS,
|
|
365
|
+
placeholder="{{ nodes.account.balance }}",
|
|
366
|
+
example="{{ nodes.account.balance }}",
|
|
367
|
+
expected_type="any",
|
|
368
|
+
),
|
|
369
|
+
"operator": FieldSchema(
|
|
370
|
+
name="operator",
|
|
371
|
+
type=FieldType.ENUM,
|
|
372
|
+
description="i18n:fields.IfNode.operator",
|
|
373
|
+
default="==",
|
|
374
|
+
enum_values=[
|
|
375
|
+
"==", "!=", ">", ">=", "<", "<=",
|
|
376
|
+
"in", "not_in",
|
|
377
|
+
"contains", "not_contains",
|
|
378
|
+
"is_empty", "is_not_empty",
|
|
379
|
+
],
|
|
380
|
+
enum_labels={
|
|
381
|
+
"==": "i18n:enums.if_operator.eq",
|
|
382
|
+
"!=": "i18n:enums.if_operator.ne",
|
|
383
|
+
">": "i18n:enums.if_operator.gt",
|
|
384
|
+
">=": "i18n:enums.if_operator.gte",
|
|
385
|
+
"<": "i18n:enums.if_operator.lt",
|
|
386
|
+
"<=": "i18n:enums.if_operator.lte",
|
|
387
|
+
"in": "i18n:enums.if_operator.in",
|
|
388
|
+
"not_in": "i18n:enums.if_operator.not_in",
|
|
389
|
+
"contains": "i18n:enums.if_operator.contains",
|
|
390
|
+
"not_contains": "i18n:enums.if_operator.not_contains",
|
|
391
|
+
"is_empty": "i18n:enums.if_operator.is_empty",
|
|
392
|
+
"is_not_empty": "i18n:enums.if_operator.is_not_empty",
|
|
393
|
+
},
|
|
394
|
+
required=True,
|
|
395
|
+
expression_mode=ExpressionMode.FIXED_ONLY,
|
|
396
|
+
category=FieldCategory.PARAMETERS,
|
|
397
|
+
),
|
|
398
|
+
"right": FieldSchema(
|
|
399
|
+
name="right",
|
|
400
|
+
type=FieldType.STRING,
|
|
401
|
+
description="i18n:fields.IfNode.right",
|
|
402
|
+
required=False,
|
|
403
|
+
expression_mode=ExpressionMode.BOTH,
|
|
404
|
+
category=FieldCategory.PARAMETERS,
|
|
405
|
+
placeholder="1000000",
|
|
406
|
+
example="1000000",
|
|
407
|
+
expected_type="any",
|
|
408
|
+
visible_when={
|
|
409
|
+
"operator": [
|
|
410
|
+
"==", "!=", ">", ">=", "<", "<=",
|
|
411
|
+
"in", "not_in", "contains", "not_contains",
|
|
412
|
+
],
|
|
413
|
+
},
|
|
414
|
+
),
|
|
415
|
+
}
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/realtime_futures.py
RENAMED
|
@@ -20,7 +20,7 @@ from programgarden_core.nodes.base import (
|
|
|
20
20
|
OutputPort,
|
|
21
21
|
ProductScope,
|
|
22
22
|
BrokerProvider,
|
|
23
|
-
|
|
23
|
+
OVERSEAS_FUTURES_REAL_BALANCE_FIELDS,
|
|
24
24
|
MARKET_DATA_FULL_FIELDS,
|
|
25
25
|
OHLCV_DATA_FIELDS,
|
|
26
26
|
ORDER_EVENT_FIELDS,
|
|
@@ -130,7 +130,7 @@ class OverseasFuturesRealAccountNode(BaseNode):
|
|
|
130
130
|
_inputs: List[InputPort] = []
|
|
131
131
|
_outputs: List[OutputPort] = [
|
|
132
132
|
OutputPort(name="held_symbols", type="symbol_list", description="i18n:ports.held_symbols", fields=SYMBOL_LIST_FIELDS),
|
|
133
|
-
OutputPort(name="balance", type="balance_data", description="i18n:ports.balance", fields=
|
|
133
|
+
OutputPort(name="balance", type="balance_data", description="i18n:ports.balance", fields=OVERSEAS_FUTURES_REAL_BALANCE_FIELDS),
|
|
134
134
|
OutputPort(name="open_orders", type="order_list", description="i18n:ports.open_orders", fields=ORDER_LIST_FIELDS),
|
|
135
135
|
OutputPort(name="positions", type="position_data", description="i18n:ports.positions", fields=POSITION_FIELDS),
|
|
136
136
|
]
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/realtime_stock.py
RENAMED
|
@@ -20,7 +20,7 @@ from programgarden_core.nodes.base import (
|
|
|
20
20
|
OutputPort,
|
|
21
21
|
ProductScope,
|
|
22
22
|
BrokerProvider,
|
|
23
|
-
|
|
23
|
+
OVERSEAS_STOCK_REAL_BALANCE_FIELDS,
|
|
24
24
|
MARKET_DATA_FULL_FIELDS,
|
|
25
25
|
OHLCV_DATA_FIELDS,
|
|
26
26
|
ORDER_EVENT_FIELDS,
|
|
@@ -134,7 +134,7 @@ class OverseasStockRealAccountNode(BaseNode):
|
|
|
134
134
|
_inputs: List[InputPort] = []
|
|
135
135
|
_outputs: List[OutputPort] = [
|
|
136
136
|
OutputPort(name="held_symbols", type="symbol_list", description="i18n:ports.held_symbols", fields=SYMBOL_LIST_FIELDS),
|
|
137
|
-
OutputPort(name="balance", type="balance_data", description="i18n:ports.balance", fields=
|
|
137
|
+
OutputPort(name="balance", type="balance_data", description="i18n:ports.balance", fields=OVERSEAS_STOCK_REAL_BALANCE_FIELDS),
|
|
138
138
|
OutputPort(name="open_orders", type="order_list", description="i18n:ports.open_orders", fields=ORDER_LIST_FIELDS),
|
|
139
139
|
OutputPort(name="positions", type="position_data", description="i18n:ports.positions", fields=POSITION_FIELDS),
|
|
140
140
|
]
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/registry/node_registry.py
RENAMED
|
@@ -76,10 +76,11 @@ class NodeTypeRegistry:
|
|
|
76
76
|
"""Register built-in node types"""
|
|
77
77
|
# 지연 임포트로 순환 참조 방지
|
|
78
78
|
from programgarden_core.nodes import (
|
|
79
|
-
StartNode, ThrottleNode, SplitNode, AggregateNode,
|
|
79
|
+
StartNode, ThrottleNode, SplitNode, AggregateNode, IfNode,
|
|
80
80
|
OverseasStockBrokerNode, OverseasFuturesBrokerNode,
|
|
81
81
|
# Market - Stock (해외주식)
|
|
82
|
-
OverseasStockMarketDataNode,
|
|
82
|
+
OverseasStockMarketDataNode, OverseasStockFundamentalNode,
|
|
83
|
+
OverseasStockHistoricalDataNode,
|
|
83
84
|
OverseasStockRealMarketDataNode,
|
|
84
85
|
OverseasStockSymbolQueryNode,
|
|
85
86
|
# Market - Futures (해외선물)
|
|
@@ -110,11 +111,12 @@ class NodeTypeRegistry:
|
|
|
110
111
|
|
|
111
112
|
node_classes = [
|
|
112
113
|
# Infra
|
|
113
|
-
StartNode, ThrottleNode, SplitNode, AggregateNode,
|
|
114
|
+
StartNode, ThrottleNode, SplitNode, AggregateNode, IfNode,
|
|
114
115
|
# Broker (상품별 분리)
|
|
115
116
|
OverseasStockBrokerNode, OverseasFuturesBrokerNode,
|
|
116
117
|
# Market - Stock (해외주식)
|
|
117
|
-
OverseasStockMarketDataNode,
|
|
118
|
+
OverseasStockMarketDataNode, OverseasStockFundamentalNode,
|
|
119
|
+
OverseasStockHistoricalDataNode,
|
|
118
120
|
OverseasStockRealMarketDataNode,
|
|
119
121
|
OverseasStockSymbolQueryNode,
|
|
120
122
|
# Market - Futures (해외선물)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/bases/components.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/expression/__init__.py
RENAMED
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/expression/evaluator.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/models/connection_rule.py
RENAMED
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/models/credential.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/models/field_binding.py
RENAMED
|
File without changes
|
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/models/plugin_resource.py
RENAMED
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/models/resilience.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/backtest_futures.py
RENAMED
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/backtest_stock.py
RENAMED
|
File without changes
|
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/calculation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/data_futures.py
RENAMED
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/data_stock.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/open_orders_stock.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/symbol_futures.py
RENAMED
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/nodes/symbol_stock.py
RENAMED
|
File without changes
|
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/presets/__init__.py
RENAMED
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/presets/news_analyst.json
RENAMED
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/presets/risk_manager.json
RENAMED
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/presets/strategist.json
RENAMED
|
File without changes
|
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/registry/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{programgarden_core-1.2.0 → programgarden_core-1.4.0}/programgarden_core/registry/plugin_registry.py
RENAMED
|
File without changes
|
|
File without changes
|