Skip to main content

ProgramGarden

ProgramGarden은 AI 시대에 맞춰 파이썬을 모르는 투자자도 개인화된 시스템 트레이딩을 자동으로 수행할 수 있게 돕는 노드 기반 자동매매 DSL(Domain Specific Language) 오픈소스입니다.

노드를 조합하여 워크플로우를 정의하고, 실행 엔진이 이를 자동으로 처리합니다. LS증권 OpenAPI를 메인으로 해외 주식/선물 거래 자동화를 지원합니다.

공식 문서 및 커뮤니티

설치

pip install programgarden

# Poetry 사용 시 (개발 환경)
poetry add programgarden

요구 사항: Python 3.12+

빠른 시작

동기 실행

from programgarden import ProgramGarden

pg = ProgramGarden()

# 워크플로우 검증
result = pg.validate(workflow_definition)

# 워크플로우 실행 (완료 대기)
job_state = pg.run(
    definition=workflow_definition,
    context={"param": "value"},
    secrets={"appkey": "...", "appsecret": "..."},
    wait=True,
    timeout=60.0,
)

비동기 실행

from programgarden import ProgramGarden

pg = ProgramGarden()

# 워크플로우 비동기 실행 (리스너 연결)
job = await pg.run_async(
    definition=workflow_definition,
    context={"param": "value"},
    listeners=[MyExecutionListener()],
)

# 실행 중 제어
await job.stop()

Broker account trackers belong to the workflow job. Normal completion, stop(), cancel(), and force_stop() cancel pending broker startup/history tasks, stop account polling, and close each tracker's dedicated WebSocket. Late account PnL callbacks do not restart work after shutdown. This cleanup also covers partially initialized trackers and leaves other jobs running. Scheduled cycles reuse the same broker account tracker, including pending startup. A failed startup stops its tracker and closes its connection before a later cycle may try again; no immediate retry or extra workflow node is introduced. Already queued or in-flight PnL notifications have up to one second to finish after account trackers stop, before listeners close. On timeout, cleanup logs the pending count and cancels those tasks, allowing another 0.25 seconds for cancellation. A listener that suppresses cancellation is reported and remains tracked; it cannot hold job shutdown indefinitely. Delivery beyond this bounded grace is not guaranteed.

Overseas-stock historical queries preserve the exchange supplied by each symbol, including when the account has no holdings. Item-bound consumers of an explicitly empty selected upstream list are skipped before expression evaluation; this also covers SymbolFilter output and explicit edge ports. Empty condition gates retain their stronger literal-order protection, while non-item aggregate/report nodes continue to run. A skipped order keeps its declared output ports and a no-signal result row. These safeguards do not establish that upstream market data is valid.

For one-shot workflows, an unhandled order_result.success=False returned directly by a main-flow node makes the final job status failed and emits WORKFLOW_FAILED. The original broker message remains in node diagnostics and the failure statistics. Successful downstream nodes do not erase that rejection. reason="no_signal" stays a normal no-op. Scheduled/resident workflows continue after a rejected cycle; SplitNode and automatic iteration retain their existing item-error continuation policies. Final failure is not inferred from cumulative errors_count or old logs. Raised main-node exceptions retain the existing fail-fast behavior.

New-order nodes for overseas stocks, overseas futures, and Korea stocks expose the catalog's result port as a list of outcome rows: {{ nodes.order.result }} can feed TableDisplayNode directly. Each row copies the final order_result and includes order_id from the existing top-level or nested order number. Legacy order_result and order_id outputs are unchanged. The projection occurs after fill confirmation, and fractional-remainder annotation; an accepted order is not promoted to a fill without confirmation. Rejections and no_signal keep their original diagnostics/reason as an outcome row, with no fabricated order number. Dry runs add a simulated row while retaining the legacy flat simulation envelope; request/credential data is not copied into the row. Automatic iteration merges these rows into one list. Implicit SplitNode collection of a new-order result retains its legacy order_result row shape; explicit nodes.order.result bindings always read the list. Modify/cancel nodes retain their separately declared modify_result/cancel_result ports and are outside this change.

Stock read failures

Stock open-order queries include current-day orders (ThdayBnsAppYn="1"). OpenOrdersNode reports unusable COSAQ00102 responses with error, reason="fetch_failed", and the original TR, HTTP status and broker response fields in diagnostics. Its legacy empty payload/count remains for compatibility; an error result is unavailable, not evidence of zero orders. A successful empty response requires documented success plus parsed echo and aggregate blocks. Unknown broker codes receive no inferred meaning.

Stock MarketDataNode preserves failed g3101 attempts under failures. An entirely failed fetch returns error and reason="fetch_failed"; mixed results retain usable values with _partial_failure and _failure_reason. The existing exchange fallback and empty upstream no-signal behavior remain. Futures master errors likewise report the observed catalogue and original broker fields without inferring account entitlement, token or quota causes.

Dry Run (워크플로우 검증용 모의 실행)

실제 주문/알림/Realtime WebSocket 연결 없이 워크플로우를 검증합니다.

  • ScheduleNode / TradingHoursFilterNode → 1 cycle 후 즉시 종료
  • 주문 노드 → LS API 미호출, {"order_id": "DRYRUN-<uuid>", "status": "simulated", ...} 반환
  • Realtime 노드 → WebSocket 미개방, {"status": "skipped_dry_run"} 반환
  • Messaging 노드(Telegram 등) → no-op, {"status": "simulated"} 반환
  • 조회/백테스트 노드 → 기존 동작 유지 (실제 API 경로)
job = await pg.run_async(
    definition=workflow_definition,
    context={"dry_run": True},
    secrets={...},
)

워크플로우 정의 (JSON)

{
  "nodes": [
    {"id": "broker", "type": "OverseasStockBrokerNode", "credential_id": "cred-1"},
    {"id": "account", "type": "OverseasStockAccountNode"},
    {"id": "rsi", "type": "ConditionNode", "plugin": "RSI", "data": "{{ nodes.historical.values }}"}
  ],
  "edges": [
    {"from": "broker", "to": "account"},
    {"from": "account", "to": "rsi"}
  ],
  "credentials": [
    {
      "credential_id": "cred-1",
      "type": "broker_ls_overseas_stock",
      "data": [
        {"key": "appkey", "value": "", "type": "password", "label": "App Key"},
        {"key": "appsecret", "value": "", "type": "password", "label": "App Secret"}
      ]
    }
  ]
}

주요 특징

  • 노드 기반 DSL: 74개 내장 노드를 조합하여 코딩 없이 자동매매 전략 구성
  • 실시간 처리: WebSocket 기반 실시간 시세, 계좌, 체결 이벤트 수신
  • AI Agent 통합: LLMModelNode + AIAgentNode로 LLM 기반 분석/의사결정
  • 플러그인 확장: 67개 내장 전략 플러그인 (RSI, MACD, 볼린저밴드, 이치모쿠, 듀얼모멘텀, 터틀브레이크아웃 등)
  • ExecutionListener: 10개 이상의 콜백으로 실행 상태 실시간 모니터링
  • 위험 관리: WorkflowRiskTracker로 HWM/drawdown 추적, 포지션 사이징
  • 동적 노드 주입: 런타임에 커스텀 노드 등록 및 실행

아키텍처

5-Layer Architecture:
1. Registry Layer   - 노드/플러그인 메타데이터 (76개 노드, 77개 플러그인)
2. Credential Layer - 인증 정보 관리
3. Definition Layer - JSON 워크플로우 정의 (노드, 엣지, 크레덴셜)
4. Job Layer        - 상태 유지 실행 인스턴스 (최대 24시간 장기 실행)
5. Event Layer      - ExecutionListener 콜백 이벤트

ExecutionListener 콜백

콜백 설명
on_node_state_change 노드 실행 상태 변경
on_edge_state_change 엣지 실행 상태 변경
on_log 로그 이벤트
on_job_state_change Job 생명주기
on_display_data 차트/테이블 출력 데이터
on_workflow_pnl_update 실시간 수익률 (FIFO 기반)
on_retry 노드 재시도 이벤트
on_token_usage AI 토큰 사용량
on_ai_tool_call AI Agent 도구 호출
on_llm_stream LLM 스트리밍 출력
on_risk_event 위험 임계값 이벤트
on_notification 투자자 알림 (시그널, 리스크, 워크플로우 상태, 스케줄, 재시도 소진)

변경 로그

자세한 변경 사항은 CHANGELOG.md를 참고하세요.

Metadata

Release files for programgarden 3.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for programgarden 3.0.0
File Size Uploaded Provenance Actions
programgarden-3.0.0.tar.gz 515.5 kB Without provenance Details for programgarden-3.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for programgarden 3.0.0
File Interpreter ABI Platform Actions
programgarden-3.0.0-py3-none-any.whl Python 3 none any Details for programgarden-3.0.0-py3-none-any.whl

Total release size: 1.1 MB

Release files / programgarden-3.0.0.tar.gz

Download URL programgarden-3.0.0.tar.gz
Size 515.5 kB
Tags Source
SHA-256 checksum
How to use checksums
60910509387231d8d8f46e28bc536d57ce320b79543f66df556962ba692aa7f5
BLAKE2b-256 checksum
How to use checksums
e345b7e3412953e03e6bcc945106554aa8a17be7a6e6d794e4d15e8f82d9d4f4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.4.1 CPython/3.12.13 Darwin/27.0.0

Release files / programgarden-3.0.0-py3-none-any.whl

Download URL programgarden-3.0.0-py3-none-any.whl
Size 546.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c0b44986d07923ec16e33d8fa4a4f14e905379096330bdd65cf25fe14616cbda
BLAKE2b-256 checksum
How to use checksums
5c14e361733aef42255a092ff3c85025c409be5dfe7fd64f79c5584fe1275153
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.4.1 CPython/3.12.13 Darwin/27.0.0

Security for programgarden 3.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

3.0.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page