programgarden-community 2.3.0__tar.gz → 2.3.2__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 (109) hide show
  1. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/PKG-INFO +2 -2
  2. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/nodes/messaging/telegram.py +10 -6
  3. programgarden_community-2.3.2/programgarden_community/plugins/_replay_clock.py +30 -0
  4. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/roll_management/__init__.py +3 -1
  5. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/time_based_exit/__init__.py +4 -1
  6. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/pyproject.toml +2 -2
  7. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/README.md +0 -0
  8. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/__init__.py +0 -0
  9. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/nodes/__init__.py +0 -0
  10. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/nodes/analysis/__init__.py +0 -0
  11. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/nodes/analysis/performance_report.py +0 -0
  12. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/nodes/messaging/__init__.py +0 -0
  13. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/nodes_registry.py +0 -0
  14. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/__init__.py +0 -0
  15. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/_position_qty.py +0 -0
  16. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/_ta_common.py +0 -0
  17. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/adx/__init__.py +0 -0
  18. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/aroon/__init__.py +0 -0
  19. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/atr/__init__.py +0 -0
  20. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/beta_hedge/__init__.py +0 -0
  21. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/bollinger_bands/README.md +0 -0
  22. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/bollinger_bands/__init__.py +0 -0
  23. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/breakout_retest/__init__.py +0 -0
  24. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/calendar_spread/__init__.py +0 -0
  25. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/calmar_ratio/__init__.py +0 -0
  26. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/cci/__init__.py +0 -0
  27. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/cmf/__init__.py +0 -0
  28. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/cmo/__init__.py +0 -0
  29. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/connors_rsi/__init__.py +0 -0
  30. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/contango_backwardation/__init__.py +0 -0
  31. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/coppock_curve/__init__.py +0 -0
  32. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/correlation_analysis/__init__.py +0 -0
  33. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/correlation_guard/__init__.py +0 -0
  34. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/dcf_fair_value/__init__.py +0 -0
  35. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/doji/__init__.py +0 -0
  36. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/drawdown_protection/__init__.py +0 -0
  37. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/dual_momentum/README.md +0 -0
  38. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/dual_momentum/__init__.py +0 -0
  39. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/dynamic_stop_loss/__init__.py +0 -0
  40. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/elder_ray/__init__.py +0 -0
  41. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/engulfing/__init__.py +0 -0
  42. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/ev_ebitda_screen/__init__.py +0 -0
  43. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/fisher_transform/__init__.py +0 -0
  44. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/golden_ratio/__init__.py +0 -0
  45. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/graham_number/__init__.py +0 -0
  46. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/hammer_shooting_star/__init__.py +0 -0
  47. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/heikin_ashi/__init__.py +0 -0
  48. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/hurst_exponent/__init__.py +0 -0
  49. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/ichimoku_cloud/__init__.py +0 -0
  50. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/kdj/__init__.py +0 -0
  51. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/kelly_criterion/__init__.py +0 -0
  52. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/keltner_channel/__init__.py +0 -0
  53. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/level_touch/__init__.py +0 -0
  54. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/ma_cross/README.md +0 -0
  55. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/ma_cross/__init__.py +0 -0
  56. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/macd/README.md +0 -0
  57. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/macd/__init__.py +0 -0
  58. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/magic_formula/__init__.py +0 -0
  59. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/market_internals/__init__.py +0 -0
  60. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/max_position_limit/__init__.py +0 -0
  61. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/mean_reversion/__init__.py +0 -0
  62. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/mfi/__init__.py +0 -0
  63. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/momentum_rank/__init__.py +0 -0
  64. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/morning_evening_star/__init__.py +0 -0
  65. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/multi_timeframe_confirmation/__init__.py +0 -0
  66. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/obv/__init__.py +0 -0
  67. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/pair_trading/__init__.py +0 -0
  68. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/parabolic_sar/__init__.py +0 -0
  69. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/partial_take_profit/__init__.py +0 -0
  70. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/piotroski_f_score/__init__.py +0 -0
  71. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/pivot_point/__init__.py +0 -0
  72. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/portfolio_optimizer/__init__.py +0 -0
  73. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/price_channel/__init__.py +0 -0
  74. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/profit_target/README.md +0 -0
  75. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/profit_target/__init__.py +0 -0
  76. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/qqe/__init__.py +0 -0
  77. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/regime_detection/__init__.py +0 -0
  78. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/relative_strength/__init__.py +0 -0
  79. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/risk_parity/__init__.py +0 -0
  80. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/rsi/README.md +0 -0
  81. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/rsi/__init__.py +0 -0
  82. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/rsi_divergence/__init__.py +0 -0
  83. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/schaff_trend_cycle/__init__.py +0 -0
  84. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/seasonal_filter/__init__.py +0 -0
  85. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/sharpe_ratio_monitor/__init__.py +0 -0
  86. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/sortino_ratio/__init__.py +0 -0
  87. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/squeeze_momentum/__init__.py +0 -0
  88. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/stochastic/__init__.py +0 -0
  89. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/stop_loss/README.md +0 -0
  90. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/stop_loss/__init__.py +0 -0
  91. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/supertrend/__init__.py +0 -0
  92. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/support_resistance_levels/__init__.py +0 -0
  93. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/tactical_asset_allocation/__init__.py +0 -0
  94. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/three_line_strike/__init__.py +0 -0
  95. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/time_series_momentum/__init__.py +0 -0
  96. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/trailing_stop/README.md +0 -0
  97. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/trailing_stop/__init__.py +0 -0
  98. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/trix/__init__.py +0 -0
  99. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/turtle_breakout/__init__.py +0 -0
  100. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/ultimate_oscillator/__init__.py +0 -0
  101. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/var_cvar_monitor/__init__.py +0 -0
  102. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/volatility_breakout/__init__.py +0 -0
  103. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/volatility_position_sizing/__init__.py +0 -0
  104. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/volume_spike/README.md +0 -0
  105. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/volume_spike/__init__.py +0 -0
  106. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/vortex_indicator/__init__.py +0 -0
  107. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/vwap/__init__.py +0 -0
  108. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/williams_r/__init__.py +0 -0
  109. {programgarden_community-2.3.0 → programgarden_community-2.3.2}/programgarden_community/plugins/z_score/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: programgarden-community
3
- Version: 2.3.0
3
+ Version: 2.3.2
4
4
  Summary: ProgramGarden Community - 전략 플러그인 모음
5
5
  License-Expression: AGPL-3.0-or-later
6
6
  Author: 프로그램동산
@@ -18,7 +18,7 @@ Provides-Extra: portfolio
18
18
  Provides-Extra: quant-all
19
19
  Provides-Extra: xlsx
20
20
  Requires-Dist: packaging (>=23) ; extra == "portfolio" or extra == "quant-all"
21
- Requires-Dist: programgarden-core (>=2.5.0,<3.0.0)
21
+ Requires-Dist: programgarden-core (>=2.5.1,<3.0.0)
22
22
  Requires-Dist: pypdf (>=4.0.0)
23
23
  Requires-Dist: pyportfolioopt (>=1.6,<2) ; (python_version < "3.15") and (extra == "portfolio" or extra == "quant-all")
24
24
  Requires-Dist: quantstats (>=0.0.81,<0.1) ; extra == "perf" or extra == "quant-all"
@@ -48,16 +48,18 @@ class TelegramNode(BaseMessagingNode):
48
48
  type: Literal["TelegramNode"] = "TelegramNode"
49
49
 
50
50
  # 연결(자격증명) 선언 — 챗봇/편집기/검증기 공용. 텔레그램 봇 토큰은 발송에 필요하다.
51
+ # missing="ask" (오너 결정 2026-09-28): 봇 토큰이 없으면 챗봇이 먼저 등록을 묻고,
52
+ # 사용자가 "봇 없이 진행" 이라고 명시할 때만 초안으로 저장한다("draft" 의 조용한 자동 초안과 구분).
51
53
  _connection: ClassVar[Dict[str, Any]] = {
52
54
  "purpose": "notify",
53
55
  "need": "run",
54
56
  "when": "always",
55
57
  "label_key": "connection.TelegramNode.label",
56
58
  "presets": [],
57
- "missing": "draft",
59
+ "missing": "ask",
58
60
  }
59
61
 
60
- description: str = "Send Telegram messages using a registered bot token and receiving chat ID; key-free drafts can be saved before linking credentials."
62
+ description: str = "Send Telegram messages using a registered bot token and receiving chat ID; the chatbot asks the user to register the bot before build and only saves a key-free draft when the user says to proceed without it."
61
63
 
62
64
  # 노드 아이콘 (텔레그램 로고)
63
65
  _img_url: ClassVar[str] = "https://upload.wikimedia.org/wikipedia/commons/8/82/Telegram_logo.svg"
@@ -232,10 +234,12 @@ class TelegramNode(BaseMessagingNode):
232
234
  ),
233
235
  ]
234
236
 
235
- _version: ClassVar[str] = "1.0.0"
236
- _updated_at: ClassVar[str] = "2026-05-19"
237
- _change_note: ClassVar[Optional[str]] = None
238
-
237
+ _version: ClassVar[str] = "1.1.0"
238
+ _updated_at: ClassVar[str] = "2026-09-28"
239
+ _change_note: ClassVar[Optional[str]] = (
240
+ "connection.missing='ask' — chatbot asks the user to register the Telegram bot before build"
241
+ )
242
+
239
243
  @classmethod
240
244
  def get_field_schema(cls) -> Dict[str, "FieldSchema"]:
241
245
  """
@@ -0,0 +1,30 @@
1
+ """The replay fixture clock for plugins that read the current date or time.
2
+
3
+ A credential-free replay (programgarden ``validation_replay``) runs a workflow
4
+ at one fixed instant, ``context.validation_as_of`` (an ISO-8601 string with a
5
+ timezone). A plugin that compares a stored or parsed date with "now" reads that
6
+ instant instead of the wall clock, so the same replay always takes the same
7
+ branch. Live contexts have no ``validation_as_of`` and keep the wall clock.
8
+ """
9
+
10
+ from datetime import datetime
11
+ from typing import Any, Optional
12
+
13
+
14
+ def fixture_now(context: Any) -> Optional[datetime]:
15
+ """The replay instant as a naive datetime in its own offset, or None live.
16
+
17
+ Same rule as ``programgarden_core.expression.evaluator.DateNamespace``: the
18
+ instant keeps the wall time of the offset it was written in.
19
+ """
20
+ value = getattr(context, "validation_as_of", None) if context is not None else None
21
+ if not isinstance(value, str) or not value:
22
+ return None
23
+ try:
24
+ instant = datetime.fromisoformat(value.replace("Z", "+00:00"))
25
+ except ValueError:
26
+ return None
27
+ if instant.tzinfo is None or instant.utcoffset() is None:
28
+ return None
29
+ return instant.replace(tzinfo=None)
30
+
@@ -32,6 +32,7 @@ from programgarden_core.registry import PluginSchema
32
32
  from programgarden_core.registry.plugin_registry import PluginCategory, ProductType
33
33
 
34
34
  from .._position_qty import coerce_number, preserve_qty
35
+ from .._replay_clock import fixture_now
35
36
 
36
37
  logger = logging.getLogger(__name__)
37
38
 
@@ -174,7 +175,8 @@ async def roll_management_condition(
174
175
  "analysis": {"error": "No positions data"},
175
176
  }
176
177
 
177
- now = datetime.now()
178
+ # A replay judges the expiry distance at its fixture instant (live: wall clock).
179
+ now = fixture_now(context) or datetime.now()
178
180
  passed, failed, symbol_results = [], [], []
179
181
 
180
182
  # strategy_state 접근 — 메서드 이름·호출 규약은 **실제 트래커**(WorkflowRiskTracker)에
@@ -64,6 +64,7 @@ from programgarden_core.registry import PluginSchema
64
64
  from programgarden_core.registry.plugin_registry import PluginCategory, ProductType
65
65
 
66
66
  from .._position_qty import preserve_qty
67
+ from .._replay_clock import fixture_now
67
68
 
68
69
  logger = logging.getLogger(__name__)
69
70
 
@@ -227,7 +228,9 @@ async def time_based_exit_condition(
227
228
  "analysis": {"error": "No positions data", "stale_state_cleared": stale},
228
229
  }
229
230
 
230
- today = date.today()
231
+ # A replay counts holding days at its fixture date (live: wall clock).
232
+ _fixture_instant = fixture_now(context)
233
+ today = _fixture_instant.date() if _fixture_instant is not None else date.today()
231
234
  today_str = today.isoformat()
232
235
 
233
236
  passed, failed, symbol_results = [], [], []
@@ -5,7 +5,7 @@ authors = [
5
5
  homepage = "https://programgarden.com"
6
6
  requires-python = ">=3.12"
7
7
  name = "programgarden-community"
8
- version = "2.3.0"
8
+ version = "2.3.2"
9
9
  license = "AGPL-3.0-or-later"
10
10
  description = "ProgramGarden Community - 전략 플러그인 모음"
11
11
  readme = "README.md"
@@ -16,7 +16,7 @@ packages = [
16
16
  ]
17
17
 
18
18
  [tool.poetry.dependencies]
19
- programgarden-core = "^2.5.0"
19
+ programgarden-core = "^2.5.1"
20
20
  pypdf = ">=4.0.0"
21
21
  # Optional heavy quant deps (extras). 3.14 wheels validated (plan §1.3).
22
22
  # Only pyportfolioopt carries a python<3.15 marker to fence scikit-base (hard-capped