Breakout trading plan evaluation engine for cryptocurrency trading
Project description
TA2 App - Breakout Trading Plan Evaluation Engine
A trading algorithm system that implements a breakout plan evaluation engine for cryptocurrency trading. The system processes real-time market data (candlesticks and order book snapshots) to evaluate breakout trading plans and emit entry signals.
Features
- Breakout Detection: Identifies when price breaks through predefined levels with proper confirmation
- Volume Confirmation: Uses relative volume (RVOL) to validate breakouts
- Volatility-Aware Analysis: Employs ATR (Average True Range) and NATR for dynamic thresholds
- Order Book Analysis: Monitors liquidity sweeps and imbalances
- State Machine Management: Tracks plan lifecycle (PENDING → BREAK_SEEN → BREAK_CONFIRMED → TRIGGERED)
- Retest Capability: Optional retest mode for polarity flip confirmations
- Invalidation Rules: Pre-trigger cancellation conditions (price limits, time expiry)
- Signal Delivery System: HTTP POST delivery for webhook integration
- File-Based Delivery: JSON/JSONL format output with rotation support
- Signal Persistence: SQLite-based audit trails with query capabilities
- Configurable Delivery: Multiple destinations with filtering and retry logic
Architecture
The system follows functional programming principles with immutable state management:
- Data Ingestion Layer: Candlestick and order book processing
- Evaluation Engine: 1-second tick processing with multi-timeframe analysis
- Signal Emission: Complete signal emission system with multiple delivery methods, persistence, and validation
- State Machine: Explicit breakout plan lifecycle management
- Configuration: 3-tier precedence (global → instrument → plan overrides)
Tech Stack
- Python 3.9+: Core language
- Standard Library: SQLite (persistence), urllib (HTTP delivery), json (serialization)
- Dependencies: Currently uses only standard library modules for maximum compatibility
- Future Dependencies: pandas, numpy, pydantic, talib (when data processing is implemented)
- Testing: pytest (when test framework is implemented)
- Code Quality: ruff, mypy (when build tools are configured)
Installation
Prerequisites
- Python 3.9 or higher
- No external dependencies (uses standard library only)
Setup
- Clone the repository:
git clone https://github.com/esshka/ta2a.git
cd ta2a
- Verify Python installation:
python3 --version
- Test the implementation:
python3 -m py_compile ta2_app/config/signal_delivery.py
Future Setup (when dependencies are added)
- Poetry for dependency management
- Pre-commit hooks for code quality
- TA-Lib for technical analysis indicators
Development
Current Status
The project is in active development with the following completed:
- ✅ Signal Emission System: Complete delivery infrastructure with HTTP, file, and stdout outputs
- ✅ Signal Persistence: SQLite-based audit trails and query capabilities
- ✅ Signal Validation: JSON schema validation according to dev_proto.md
- ✅ Configuration System: Flexible delivery destination configuration
- ⏳ Data Processing: Candlestick and order book parsing (planned)
- ⏳ Breakout Detection: Core trading algorithm (planned)
- ⏳ Testing Framework: Comprehensive test suite (planned)
Code Quality (Future)
When build tools are configured:
# Format code
poetry run ruff format
# Lint code
poetry run ruff check
# Type checking
poetry run mypy ta2_app
Project Structure
ta2_app/
├── config/ # Configuration management (✅ Extended with signal delivery)
├── data/ # Data ingestion and normalization (⏳ Planned)
├── delivery/ # Signal delivery mechanisms (✅ NEW: HTTP, file, stdout)
├── metrics/ # Technical indicator calculations (✅ Core framework)
├── models/ # Data models and contracts (✅ Core models)
├── persistence/ # Signal storage and audit trails (✅ NEW: SQLite-based)
├── signals/ # Signal emission and scoring (✅ Core framework)
├── state/ # State machine and plan runtime (✅ Core implementation)
├── utils/ # Utility functions (✅ Basic utilities)
├── validation/ # Signal format validation (✅ NEW: JSON schema)
└── engine.py # Main evaluation engine coordinator (✅ Core framework)
Configuration
Signal Delivery Configuration
The signal emission system supports multiple delivery destinations:
from ta2_app.config.signal_delivery import (
SignalDeliveryConfig,
create_http_destination,
create_file_destination
)
# Configure HTTP webhook delivery
http_dest = create_http_destination(
name="webhook",
url="https://api.example.com/signals",
headers={"Authorization": "Bearer token"}
)
# Configure file output
file_dest = create_file_destination(
name="audit_log",
output_path="./signals.jsonl",
format="jsonl"
)
# Create delivery configuration
config = SignalDeliveryConfig(
destinations=[http_dest, file_dest],
parallel_delivery=True,
failure_retry_attempts=3
)
Trading Parameters
The system supports 3-tier parameter precedence:
- Global defaults: Base configuration for all instruments
- Instrument-specific overrides: Per-instrument parameter adjustments
- Per-plan overrides: Individual plan customization via
extra_data.breakout_params
Signal Output Format
The system emits signals in a standardized JSON format when breakout conditions are met. Each signal contains comprehensive market data and execution metadata for downstream trading systems.
Signal Structure
{
"plan_id": "plan_123",
"state": "triggered",
"runtime": {
"armed_at": "2025-01-17T04:09:00Z",
"triggered_at": "2025-01-17T04:09:05Z",
"invalid_reason": null
},
"last_price": 3306.2,
"metrics": {
"rvol": 1.87,
"natr_pct": 1.2,
"atr": 42.1,
"pinbar": false
},
"strength_score": 83.5,
"protocol_version": "breakout-v1"
}
Field Descriptions
| Field | Type | Description |
|---|---|---|
plan_id |
String | Unique identifier for the trading plan |
state |
String | Signal state: "triggered", "invalid", or "expired" |
runtime.armed_at |
ISO8601 | Timestamp when breakout was confirmed |
runtime.triggered_at |
ISO8601 | Timestamp when signal was emitted |
runtime.invalid_reason |
String/null | Reason for invalidation (if applicable) |
last_price |
Float | Current market price at signal emission |
metrics.rvol |
Float | Relative volume ratio (current vs 20-bar average) |
metrics.natr_pct |
Float | Normalized Average True Range percentage |
metrics.atr |
Float | Average True Range value |
metrics.pinbar |
Boolean | Pinbar pattern detection flag |
strength_score |
Float | Composite quality score (0-100) for signal ranking |
protocol_version |
String | Signal format version for compatibility |
Signal States
triggered: Breakout plan successfully triggered and ready for executioninvalid: Plan invalidated due to price limits or conditions not metexpired: Plan expired due to time limits without triggering
Strength Scoring
The strength score uses a weighted algorithm to rank signal quality:
Base Score: 30 points (triggered signals)
Volume Bonus: 0-25 points (scaled by RVOL multiple)
Volatility Bonus: 25 points (when NATR in 0.5-5% range)
Pattern Bonus: 10 points (pinbar retest confirmation)
Liquidity Bonus: 10 points (order book sweep detection)
Signal Guarantees
Idempotency Mechanisms
- Exactly-Once Emission: Each state transition is emitted exactly once per plan/timestamp combination
- Database-Level Deduplication: SQLite unique constraint on
(plan_id, state, timestamp)prevents duplicate storage - In-Memory Tracking: Signal emitter maintains sent signal hashes to prevent duplicate delivery attempts
- Cross-Session Persistence: Idempotency guarantees maintained across process restarts via database state
Duplicate Prevention
- Multi-Layer Protection:
- Database unique constraints (primary protection)
- In-memory signal tracking (performance optimization)
- Timestamp-based uniqueness (allows plan reuse across time)
- Collision Handling: Database constraint violations are handled gracefully with no signal emission
- Concurrent Safety: Thread-safe operations ensure no race conditions in multi-threaded environments
Operational Guarantees
- Metrics Snapshot: All metrics captured at exact evaluation tick (no temporal drift)
- Timestamp Precision: Market timestamps used (not wall-clock time) for deterministic replay
- State Isolation: Each plan's idempotency tracking is completely isolated from others
- Delivery Idempotency: Multiple delivery attempts of the same signal are prevented
Failure Scenarios
- Process Restart: Signals already stored in database will not be re-emitted
- Network Failures: Delivery failures do not trigger duplicate signal creation
- Concurrent Processing: Multiple threads processing same tick will only emit one signal
- Database Corruption: System fails safely without emitting potentially duplicate signals
Monitoring and Validation
- Signal Audit Trail: All signals stored in
signal_storewith full metadata - Duplicate Detection: Query
SELECT plan_id, state, timestamp, COUNT(*) FROM signals GROUP BY plan_id, state, timestamp HAVING COUNT(*) > 1to detect any duplicates - Idempotency Verification: Integration tests validate idempotency across all failure scenarios
Recovery Procedures
- Duplicate Cleanup: If duplicates are detected, use
SignalStore.delete_signal()to remove extras - State Reset: Use
StateManager.clear_plan_state()to reset plan state if needed - Database Recovery: SQLite database can be rebuilt from signal audit logs if corruption occurs
Usage
Quick Start
from ta2_app.engine import BreakoutEvaluationEngine
from ta2_app.data.parsers import parse_candlestick_payload, parse_orderbook_payload
# Initialize the evaluation engine
engine = BreakoutEvaluationEngine()
# Add a breakout plan
plan = {
"id": "plan_123",
"instrument_id": "ETH-USDT-SWAP",
"direction": "short",
"entry_type": "breakout",
"entry_price": 3308.0,
"created_at": "2025-01-17T04:08:23.750427",
"extra_data": {
"entry_params": {"level": 3308},
"invalidation_conditions": [
{"type": "price_above", "level": 3360},
{"type": "time_limit", "duration_seconds": 3600}
]
}
}
engine.add_plan(plan)
# Process market data tick
candlestick_data = {
"code": "0",
"msg": "",
"data": [
["1597026383085", "3.721", "3.743", "3.677", "3.708", "8422410", "22698348.04", "12698348.04", "1"]
]
}
signals = engine.evaluate_tick(
candlestick_payload=candlestick_data,
instrument_id="ETH-USDT-SWAP"
)
# Process generated signals
for signal in signals:
print(f"Signal: {signal['state']} for plan {signal['plan_id']}")
Market Data Ingestion
Supported Data Formats
The system processes real-time market data from cryptocurrency exchanges, primarily in OKX format:
Candlestick Data Format
{
"code": "0",
"msg": "",
"data": [
["1597026383085", "3.721", "3.743", "3.677", "3.708", "8422410", "22698348.04", "12698348.04", "0"],
["1597026444085", "3.708", "3.799", "3.494", "3.72", "24912403", "67632347.24", "37632347.24", "1"]
]
}
Array Format: [timestamp_ms, open, high, low, close, volume_base, volume_quote, volume_quote_alt, confirm_flag]
timestamp_ms: Unix timestamp in millisecondsopen/high/low/close: Price values as stringsvolume_base: Base currency volumevolume_quote: Quote currency volumeconfirm_flag: "1" for closed bar, "0" for developing bar
Order Book Data Format
{
"code": "0",
"msg": "",
"data": [{
"asks": [["41006.8", "0.60038921", "0", "1"]],
"bids": [["41006.3", "0.30178218", "0", "2"]],
"ts": "1629966436396"
}]
}
Level Format: [price, size, _, _] (trailing fields ignored)
Data Ingestion Pipeline
from ta2_app.data.parsers import parse_candlestick_payload, parse_orderbook_payload
from ta2_app.data.normalizer import DataNormalizer
# Initialize data normalizer
normalizer = DataNormalizer()
# Parse candlestick data
candlestick_payload = {
"code": "0",
"msg": "",
"data": [
["1597026383085", "3.721", "3.743", "3.677", "3.708", "8422410", "22698348.04", "12698348.04", "1"]
]
}
# Normalize candlestick data
candle_result = normalizer.normalize_candlesticks(candlestick_payload)
if candle_result.success:
candle = candle_result.candle
print(f"Processed candle: {candle.close} at {candle.ts}")
# Parse order book data
orderbook_payload = {
"code": "0",
"msg": "",
"data": [{
"asks": [["3310.5", "1.5"], ["3311.0", "2.0"]],
"bids": [["3309.5", "1.2"], ["3309.0", "1.8"]],
"ts": "1629966436396"
}]
}
# Normalize order book data
book_result = normalizer.normalize_orderbook(orderbook_payload)
if book_result.success:
book = book_result.book_snap
print(f"Processed book: bid={book.bid_price}, ask={book.ask_price}")
Error Handling and Validation
from ta2_app.data.parsers import (
parse_candlestick_payload,
ParseError,
PriceSpikeError,
InvalidPriceError
)
# Enable spike filtering for wild price movements
try:
candles = parse_candlestick_payload(
payload=candlestick_data,
enable_spike_filter=True,
last_price=3308.0,
atr=42.5,
spike_multiplier=10.0
)
except PriceSpikeError as e:
print(f"Price spike detected: {e}")
except InvalidPriceError as e:
print(f"Invalid price data: {e}")
except ParseError as e:
print(f"Parsing failed: {e}")
Market Data Preparation
Data Quality Requirements
The system expects high-quality market data with the following characteristics:
- Timestamps: Accurate market timestamps (not receive timestamps)
- Price Consistency: OHLC prices must be logically consistent
- Volume Validation: Non-negative volume values
- Sequence Integrity: Proper bar sequence without gaps
- Confirmation Flags: Accurate closed/developing bar indicators
Data Validation Pipeline
from ta2_app.data.validators import validate_atr_spike_filter
# Validate individual prices against ATR-based spike detection
last_price = 3308.0
atr = 42.5
spike_multiplier = 10.0
new_price = 3305.2
is_valid = validate_atr_spike_filter(
price=new_price,
last_price=last_price,
atr=atr,
spike_multiplier=spike_multiplier
)
if not is_valid:
print(f"Price {new_price} rejected as spike")
Data Store Management
from ta2_app.data.models import InstrumentDataStore
# Create instrument-specific data store
data_store = InstrumentDataStore()
# Access rolling bars (automatically managed)
bars_1m = data_store.get_bars('1m')
bars_5m = data_store.get_bars('5m')
# Access volume history for RVOL calculation
vol_history = data_store.get_vol_history('1m')
# Update order book
data_store.update_book(book_snapshot)
# Update last price with timestamp
data_store.update_last_price(3305.2, timestamp)
Configuration
Configuration File Structure
The system uses a 3-tier configuration precedence:
- Global defaults (
config/defaults.yaml) - Instrument-specific overrides (
config/instruments.yaml) - Per-plan overrides (
extra_data.breakout_params)
Setting Up Configuration
# Copy example configuration
cp config/instruments.yaml.example config/instruments.yaml
# Edit configuration files
vim config/defaults.yaml
vim config/instruments.yaml
Global Configuration Example
# config/defaults.yaml
breakout_params:
penetration_pct: 0.05 # 0.05% minimum penetration
penetration_natr_mult: 0.25 # ATR-based penetration multiplier
min_rvol: 1.5 # 1.5x volume confirmation
confirm_close: true # Require bar close confirmation
confirm_time_ms: 750 # Hold time for time-based confirmation
allow_retest_entry: false # Use momentum vs retest entry
retest_band_pct: 0.03 # Retest proximity band
fakeout_close_invalidate: true # Invalidate on fakeout close
ob_sweep_check: true # Require order book sweep
min_break_range_atr: 0.5 # Minimum break candle range
atr_params:
period: 14 # ATR calculation period
multiplier: 2.0 # ATR multiplier
volume_params:
rvol_period: 20 # RVOL lookback period
min_volume_threshold: 1000 # Minimum volume for evaluation
Instrument-Specific Configuration
# config/instruments.yaml
instruments:
ETH-USDT-SWAP:
breakout_params:
penetration_pct: 0.08 # Higher penetration for volatile pairs
min_rvol: 2.0 # Stricter volume requirements
BTC-USDT-SWAP:
breakout_params:
penetration_pct: 0.03 # Lower penetration for stable pairs
min_rvol: 1.2 # More lenient volume requirements
Per-Plan Configuration
# Plan with custom breakout parameters
plan_with_overrides = {
"id": "plan_456",
"instrument_id": "BTC-USDT-SWAP",
"direction": "long",
"entry_type": "breakout",
"entry_price": 45000.0,
"extra_data": {
"breakout_params": {
"penetration_pct": 0.04, # Override global default
"min_rvol": 1.8, # Override instrument default
"allow_retest_entry": true # Enable retest mode
}
}
}
Configuration Validation
from ta2_app.config.validation import ConfigValidator
# Validate configuration
config_data = {
"penetration_pct": 0.05,
"min_rvol": 1.5,
"confirm_close": True
}
errors = ConfigValidator.validate_breakout_params(config_data)
if errors:
for error in errors:
print(f"Error in {error.field}: {error.message}")
Complete Usage Examples
Example 1: Basic Real-Time Processing
from ta2_app.engine import BreakoutEvaluationEngine
import json
# Initialize engine
engine = BreakoutEvaluationEngine()
# Add multiple plans
plans = [
{
"id": "eth_short_plan",
"instrument_id": "ETH-USDT-SWAP",
"direction": "short",
"entry_type": "breakout",
"entry_price": 3308.0,
"created_at": "2025-01-17T04:08:23.750427",
"extra_data": {
"invalidation_conditions": [
{"type": "price_above", "level": 3360},
{"type": "time_limit", "duration_seconds": 3600}
]
}
},
{
"id": "btc_long_plan",
"instrument_id": "BTC-USDT-SWAP",
"direction": "long",
"entry_type": "breakout",
"entry_price": 45000.0,
"created_at": "2025-01-17T04:08:23.750427",
"extra_data": {
"breakout_params": {
"allow_retest_entry": True,
"retest_band_pct": 0.02
}
}
}
]
# Add plans to engine
for plan in plans:
engine.add_plan(plan)
# Process market data updates
def process_market_update(candlestick_data, orderbook_data, instrument_id):
signals = engine.evaluate_tick(
candlestick_payload=candlestick_data,
orderbook_payload=orderbook_data,
instrument_id=instrument_id
)
for signal in signals:
print(f"🚨 Signal Generated:")
print(f" Plan: {signal['plan_id']}")
print(f" State: {signal['state']}")
print(f" Price: {signal['last_price']}")
print(f" Strength: {signal['strength_score']}")
print(f" RVOL: {signal['metrics']['rvol']}")
print(f" ATR: {signal['metrics']['atr']}")
# Simulate market data feed
eth_candlestick = {
"code": "0",
"msg": "",
"data": [
["1597026383085", "3310", "3315", "3305", "3307", "8422410", "22698348.04", "12698348.04", "1"]
]
}
eth_orderbook = {
"code": "0",
"msg": "",
"data": [{
"asks": [["3308.5", "1.5"], ["3309.0", "2.0"]],
"bids": [["3307.5", "1.2"], ["3307.0", "1.8"]],
"ts": "1597026383085"
}]
}
process_market_update(eth_candlestick, eth_orderbook, "ETH-USDT-SWAP")
Example 2: Batch Processing with State Monitoring
from ta2_app.engine import BreakoutEvaluationEngine
from datetime import datetime
# Initialize engine with custom config
engine = BreakoutEvaluationEngine(config_dir="./config")
# Add plan and monitor state transitions
plan_id = "demo_plan"
plan = {
"id": plan_id,
"instrument_id": "ETH-USDT-SWAP",
"direction": "short",
"entry_type": "breakout",
"entry_price": 3308.0,
"created_at": datetime.now().isoformat()
}
engine.add_plan(plan)
# Monitor plan state throughout evaluation
def monitor_plan_state(plan_id, engine):
state = engine.get_plan_state(plan_id)
if state:
print(f"Plan {plan_id} state: {state['state']}")
if state['break_seen']:
print(f" Break detected at: {state['break_ts']}")
if state['break_confirmed']:
print(f" Break confirmed at: {state['armed_at']}")
if state['signal_emitted']:
print(f" Signal emitted at: {state['triggered_at']}")
# Process sequence of market updates
market_updates = [
# Initial position above entry
{
"candlestick": {
"code": "0", "msg": "",
"data": [["1597026383085", "3312", "3315", "3310", "3312", "1000000", "3312000000", "3312000000", "1"]]
}
},
# Break below entry level
{
"candlestick": {
"code": "0", "msg": "",
"data": [["1597026444085", "3312", "3312", "3305", "3306", "2500000", "8265000000", "8265000000", "1"]]
}
},
# Confirmation with volume
{
"candlestick": {
"code": "0", "msg": "",
"data": [["1597026505085", "3306", "3307", "3300", "3302", "3800000", "12540000000", "12540000000", "1"]]
}
}
]
for i, update in enumerate(market_updates):
print(f"\n=== Market Update {i+1} ===")
signals = engine.evaluate_tick(
candlestick_payload=update["candlestick"],
instrument_id="ETH-USDT-SWAP"
)
monitor_plan_state(plan_id, engine)
if signals:
print(f"Generated {len(signals)} signals")
for signal in signals:
print(f" Signal: {signal}")
Example 3: Custom Signal Delivery
from ta2_app.engine import BreakoutEvaluationEngine
from ta2_app.config.signal_delivery import (
SignalDeliveryConfig,
create_http_destination,
create_file_destination
)
# Configure signal delivery
http_destination = create_http_destination(
name="trading_webhook",
url="https://api.trading-system.com/signals",
headers={"Authorization": "Bearer your-token-here"}
)
file_destination = create_file_destination(
name="audit_log",
output_path="./signals.jsonl",
format="jsonl"
)
delivery_config = SignalDeliveryConfig(
destinations=[http_destination, file_destination],
parallel_delivery=True,
failure_retry_attempts=3
)
# Initialize engine with custom signal delivery
engine = BreakoutEvaluationEngine()
# Note: Signal delivery configuration is handled by the state manager
# Process with signal delivery
plan = {
"id": "webhook_plan",
"instrument_id": "ETH-USDT-SWAP",
"direction": "short",
"entry_type": "breakout",
"entry_price": 3308.0,
"created_at": "2025-01-17T04:08:23.750427"
}
engine.add_plan(plan)
# Market data that triggers breakout
trigger_data = {
"code": "0",
"msg": "",
"data": [
["1597026383085", "3310", "3310", "3305", "3305", "5000000", "16525000000", "16525000000", "1"]
]
}
signals = engine.evaluate_tick(
candlestick_payload=trigger_data,
instrument_id="ETH-USDT-SWAP"
)
# Signals are automatically delivered to configured destinations
print(f"Generated {len(signals)} signals - delivered to webhook and file")
Testing and Validation
Running Tests
# Run all tests
pytest
# Run specific test categories
pytest tests/metrics/ # Metrics calculation tests
pytest tests/state/ # State machine tests
pytest tests/integration/ # Integration tests
pytest tests/unit/ # Unit tests
# Run tests with coverage
pytest --cov=ta2_app --cov-report=html
# Run tests with verbose output
pytest -v --tb=short
# Run specific test file
pytest tests/integration/test_full_pipeline.py -v
Test Configuration
# tests/conftest.py includes fixtures for testing
import pytest
from ta2_app.engine import BreakoutEvaluationEngine
@pytest.fixture
def engine():
return BreakoutEvaluationEngine()
@pytest.fixture
def sample_plan():
return {
"id": "test_plan",
"instrument_id": "ETH-USDT-SWAP",
"direction": "short",
"entry_type": "breakout",
"entry_price": 3308.0,
"created_at": "2025-01-17T04:08:23.750427"
}
Manual Testing
# manual_test.py - Test individual components
from ta2_app.data.parsers import parse_candlestick_payload
from ta2_app.metrics.calculator import MetricsCalculator
from ta2_app.data.models import InstrumentDataStore
# Test data parsing
test_payload = {
"code": "0",
"msg": "",
"data": [
["1597026383085", "3.721", "3.743", "3.677", "3.708", "8422410", "22698348.04", "12698348.04", "1"]
]
}
candles = parse_candlestick_payload(test_payload)
print(f"Parsed {len(candles)} candles successfully")
# Test metrics calculation
data_store = InstrumentDataStore()
calculator = MetricsCalculator()
# Add test data
for candle in candles:
bars = data_store.get_bars('1m')
bars.append(candle)
if candle.is_closed:
vol_history = data_store.get_vol_history('1m')
vol_history.append(candle.volume)
# Calculate metrics
if candles:
metrics = calculator.calculate_metrics(candles[-1], data_store, "1m")
print(f"ATR: {metrics.atr}")
print(f"NATR: {metrics.natr_pct}%")
print(f"RVOL: {metrics.rvol}")
Validation Scripts
# Validate configuration
python scripts/validate_config.py
# Run development setup
python scripts/dev_setup.py
# Run benchmark tests
python scripts/benchmark.py
Development
Development Setup
# Install development dependencies
pip install -r requirements-dev.txt
# Run development setup script
python scripts/dev_setup.py
# Install pre-commit hooks
pre-commit install
Code Quality
# Format code
ruff format ta2_app/
# Lint code
ruff check ta2_app/
# Type checking
mypy ta2_app/
# Run all quality checks
pre-commit run --all-files
Adding New Features
- New Metrics: Add to
ta2_app/metrics/directory - New Parsers: Add to
ta2_app/data/parsers.py - New Validators: Add to
ta2_app/data/validators.py - New Configuration: Update
config/defaults.yaml - New Tests: Add to appropriate
tests/subdirectory
Signal Emission System
from ta2_app.state.runtime import SignalEmitter
from ta2_app.config.signal_delivery import get_default_delivery_config
# Initialize signal emitter with delivery configuration
emitter = SignalEmitter(delivery_config=get_default_delivery_config())
# Emit a signal (signals are automatically delivered and persisted)
signal = emitter.emit_signal(
plan_id="plan_123",
signal_data={"state": "triggered", "timestamp": "2025-01-01T00:00:00Z"},
metrics=metrics_snapshot
)
License
This project is licensed under the MIT License – see the LICENSE file for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ta2_app-0.1.1.tar.gz.
File metadata
- Download URL: ta2_app-0.1.1.tar.gz
- Upload date:
- Size: 75.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
94c90363461875c6211eef66dba18dc4e0f5b74e0f61cf4bcc3b3bf18f2fbb75
|
|
| MD5 |
00a3a2ac95b5abb4112d48238165d245
|
|
| BLAKE2b-256 |
c1be8e6c0b9917896ebb9b15bd74ff3153b821ae163219c9b32bbe472e266a53
|
File details
Details for the file ta2_app-0.1.1-py3-none-any.whl.
File metadata
- Download URL: ta2_app-0.1.1-py3-none-any.whl
- Upload date:
- Size: 84.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
46dfcc7b3f2a320da4a5e71a2f20400fae5295684a9c90c39fa49a5898dd9a1f
|
|
| MD5 |
5a26b33f256ebd19701a5a498787ec6b
|
|
| BLAKE2b-256 |
6ad5fb6bd422468dad99e0361ad31555ab32d509eaec53d5d09802cfd3320e83
|