trdr 0.0.1__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 (75) hide show
  1. trdr-0.0.1/.github/workflows/publish.yml +32 -0
  2. trdr-0.0.1/.gitignore +5 -0
  3. trdr-0.0.1/.vscode/extensions.json +11 -0
  4. trdr-0.0.1/.vscode/launch.json +18 -0
  5. trdr-0.0.1/.vscode/settings.json +27 -0
  6. trdr-0.0.1/CLAUDE.md +35 -0
  7. trdr-0.0.1/PKG-INFO +13 -0
  8. trdr-0.0.1/README.md +190 -0
  9. trdr-0.0.1/examples/README.md +28 -0
  10. trdr-0.0.1/examples/no_telemetry/script.py +25 -0
  11. trdr-0.0.1/examples/strategies/first-strat.trdr +21 -0
  12. trdr-0.0.1/examples/with_telemetry/script.py +40 -0
  13. trdr-0.0.1/pyproject.toml +28 -0
  14. trdr-0.0.1/src/__init__.py +0 -0
  15. trdr-0.0.1/src/trdr/__init__.py +0 -0
  16. trdr-0.0.1/src/trdr/conftest.py +148 -0
  17. trdr-0.0.1/src/trdr/core/__init__.py +0 -0
  18. trdr-0.0.1/src/trdr/core/bar_provider/__init__.py +0 -0
  19. trdr-0.0.1/src/trdr/core/bar_provider/base_bar_provider.py +115 -0
  20. trdr-0.0.1/src/trdr/core/bar_provider/exceptions.py +40 -0
  21. trdr-0.0.1/src/trdr/core/bar_provider/models.py +38 -0
  22. trdr-0.0.1/src/trdr/core/bar_provider/yf_bar_provider/__init__.py +0 -0
  23. trdr-0.0.1/src/trdr/core/bar_provider/yf_bar_provider/test_yf_bar_provider.py +73 -0
  24. trdr-0.0.1/src/trdr/core/bar_provider/yf_bar_provider/yf_bar_provider.py +301 -0
  25. trdr-0.0.1/src/trdr/core/broker/__init__.py +0 -0
  26. trdr-0.0.1/src/trdr/core/broker/alpaca_broker/README.md +68 -0
  27. trdr-0.0.1/src/trdr/core/broker/alpaca_broker/__init__.py +0 -0
  28. trdr-0.0.1/src/trdr/core/broker/alpaca_broker/alpaca_broker.py +404 -0
  29. trdr-0.0.1/src/trdr/core/broker/base_broker.py +391 -0
  30. trdr-0.0.1/src/trdr/core/broker/exceptions.py +6 -0
  31. trdr-0.0.1/src/trdr/core/broker/mock_broker/__init__.py +0 -0
  32. trdr-0.0.1/src/trdr/core/broker/mock_broker/mock_broker.py +130 -0
  33. trdr-0.0.1/src/trdr/core/broker/mock_broker/test_mock_broker.py +394 -0
  34. trdr-0.0.1/src/trdr/core/broker/mock_broker/test_mock_broker_pdt_validation.py +277 -0
  35. trdr-0.0.1/src/trdr/core/broker/models.py +145 -0
  36. trdr-0.0.1/src/trdr/core/broker/pdt/README.md +82 -0
  37. trdr-0.0.1/src/trdr/core/broker/pdt/__init__.py +0 -0
  38. trdr-0.0.1/src/trdr/core/broker/pdt/base_pdt_strategy.py +32 -0
  39. trdr-0.0.1/src/trdr/core/broker/pdt/exceptions.py +16 -0
  40. trdr-0.0.1/src/trdr/core/broker/pdt/models.py +40 -0
  41. trdr-0.0.1/src/trdr/core/broker/pdt/nun_strategy.py +86 -0
  42. trdr-0.0.1/src/trdr/core/broker/pdt/test_pdt_evaluation.py +247 -0
  43. trdr-0.0.1/src/trdr/core/broker/pdt/wiggle_strategy.py +65 -0
  44. trdr-0.0.1/src/trdr/core/broker/pdt/yolo_strategy.py +48 -0
  45. trdr-0.0.1/src/trdr/core/broker/test_order_model.py +407 -0
  46. trdr-0.0.1/src/trdr/core/broker/test_position_model.py +638 -0
  47. trdr-0.0.1/src/trdr/core/security_provider/__init__.py +0 -0
  48. trdr-0.0.1/src/trdr/core/security_provider/base_security_provider.py +108 -0
  49. trdr-0.0.1/src/trdr/core/security_provider/models.py +197 -0
  50. trdr-0.0.1/src/trdr/core/security_provider/security_provider.py +43 -0
  51. trdr-0.0.1/src/trdr/core/security_provider/test_security_model.py +74 -0
  52. trdr-0.0.1/src/trdr/core/security_provider/test_security_provider.py +30 -0
  53. trdr-0.0.1/src/trdr/core/shared/__init__.py +0 -0
  54. trdr-0.0.1/src/trdr/core/shared/exceptions.py +2 -0
  55. trdr-0.0.1/src/trdr/core/shared/models.py +299 -0
  56. trdr-0.0.1/src/trdr/core/trading_context/__init__.py +0 -0
  57. trdr-0.0.1/src/trdr/core/trading_context/exceptions.py +2 -0
  58. trdr-0.0.1/src/trdr/core/trading_context/test_trading_context.py +481 -0
  59. trdr-0.0.1/src/trdr/core/trading_context/trading_context.py +318 -0
  60. trdr-0.0.1/src/trdr/core/trading_engine/__init__.py +0 -0
  61. trdr-0.0.1/src/trdr/core/trading_engine/trading_engine.py +222 -0
  62. trdr-0.0.1/src/trdr/dsl/__init__.py +0 -0
  63. trdr-0.0.1/src/trdr/dsl/dsl_ast.py +375 -0
  64. trdr-0.0.1/src/trdr/dsl/dsl_loader.py +99 -0
  65. trdr-0.0.1/src/trdr/dsl/lexer.py +202 -0
  66. trdr-0.0.1/src/trdr/dsl/parser.py +288 -0
  67. trdr-0.0.1/src/trdr/test_utils/__init__.py +0 -0
  68. trdr-0.0.1/src/trdr/test_utils/fake_yf_download.py +37 -0
  69. trdr-0.0.1/src/trdr/test_utils/order_generator.py +149 -0
  70. trdr-0.0.1/src/trdr/test_utils/position_generator.py +152 -0
  71. trdr-0.0.1/src/trdr/test_utils/security_generator.py +162 -0
  72. trdr-0.0.1/src/trdr/test_utils/strategies/always_buy.trdr +13 -0
  73. trdr-0.0.1/src/trdr/test_utils/strategies/always_sell.trdr +13 -0
  74. trdr-0.0.1/src/trdr/test_utils/strategies/test_strat.trdr +28 -0
  75. trdr-0.0.1/src/trdr/test_utils/test_symbols.py +505 -0
@@ -0,0 +1,32 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+
7
+ jobs:
8
+ pypi-publish:
9
+ name: upload release to PyPI
10
+ runs-on: ubuntu-latest
11
+ environment: pypi
12
+ permissions:
13
+ id-token: write
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Set up Python
19
+ uses: actions/setup-python@v5
20
+ with:
21
+ python-version: '3.12'
22
+
23
+ - name: Install dependencies
24
+ run: |
25
+ python -m pip install --upgrade pip
26
+ pip install build
27
+
28
+ - name: Build package
29
+ run: python -m build
30
+
31
+ - name: Publish to PyPI
32
+ uses: pypa/gh-action-pypi-publish@release/v1
trdr-0.0.1/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ .venv
2
+ **/__pycache__
3
+ .pytest_cache
4
+ **/.pytest_cache
5
+ **/.DS_Store
@@ -0,0 +1,11 @@
1
+ {
2
+ "recommendations": [
3
+ "esbenp.prettier-vscode",
4
+ "ms-python.black-formatter",
5
+ "ms-python.python",
6
+ "github.vscode-github-actions",
7
+ "pulumi.pulumi-vscode-tools",
8
+ "ms-python.vscode-pylance",
9
+ "eamodio.gitlens"
10
+ ]
11
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
+ "version": "0.2.0",
6
+ "configurations": [
7
+
8
+
9
+ {
10
+ "name": "Python Debugger: Current File",
11
+ "type": "debugpy",
12
+ "request": "launch",
13
+ "program": "${file}",
14
+ "console": "integratedTerminal",
15
+ "cwd": "${workspaceFolder}/examples",
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "git.enableSmartCommit": true,
3
+ "git.autofetch": true,
4
+ "editor.accessibilitySupport": "off",
5
+ "editor.foldingMaximumRegions": 15000,
6
+ "editor.formatOnSave": true,
7
+ "editor.inlineSuggest.enabled": true,
8
+ "github.copilot.enable": {
9
+ "*": true
10
+ },
11
+ "[python]": {
12
+ "editor.formatOnSave": true,
13
+ "editor.defaultFormatter": "ms-python.black-formatter"
14
+ },
15
+ "javascript.updateImportsOnFileMove.enabled": "always",
16
+ "[json]": {
17
+ "editor.defaultFormatter": "vscode.json-language-features"
18
+ },
19
+ "black-formatter.args": [
20
+ "--line-length=120"
21
+ ],
22
+ "python.testing.pytestArgs": [
23
+ "."
24
+ ],
25
+ "python.testing.unittestEnabled": false,
26
+ "python.testing.pytestEnabled": true,
27
+ }
trdr-0.0.1/CLAUDE.md ADDED
@@ -0,0 +1,35 @@
1
+ # TRDR - Trading Framework
2
+
3
+ ## Build & Test Commands
4
+
5
+ ```bash
6
+ # Install dev dependencies
7
+ pip install -e ".[dev]"
8
+
9
+ # Run all tests
10
+ pytest
11
+
12
+ # Run specific test file
13
+ pytest src/trdr/path/to/test_file.py
14
+
15
+ # Run specific test
16
+ pytest src/trdr/path/to/test_file.py::TestClass::test_method
17
+ ```
18
+
19
+ ## Code Style Guidelines
20
+
21
+ - **Naming**: Classes=PascalCase, functions/methods=snake_case, constants=UPPER_SNAKE_CASE
22
+ - **Imports**: Standard lib → third-party → local, specific imports preferred
23
+ - **Types**: Always use type annotations for parameters and return values
24
+ - **Async**: Use async/await pattern with factory `create()` methods
25
+ - **Error handling**: Custom exception hierarchy in each module
26
+ - **Documentation**: Descriptive docstrings for public methods
27
+ - **DSL**: Trading strategies defined in `.trdr` files with STRATEGY, ENTRY, EXIT sections
28
+ - **Async testing**: use asyncio.run() to run async calls in tests
29
+
30
+ ## Project Structure
31
+
32
+ - `src/trdr/core/`: Core trading components (broker, bar_provider, strategy)
33
+ - `src/trdr/dsl/`: Domain-specific language for strategy definition
34
+ - `src/trdr/conftest.py`: pytest fixtures
35
+ - `src/trdr/test_utils/`: Test utilities
trdr-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.4
2
+ Name: trdr
3
+ Version: 0.0.1
4
+ Summary: Algorithmic trading library
5
+ Author-email: developer_jeb <developer_jeb@outlook.com>
6
+ Requires-Dist: aiohttp==3.11.11
7
+ Requires-Dist: opentelemetry-api==1.30.0
8
+ Requires-Dist: opentelemetry-sdk==1.30.0
9
+ Requires-Dist: pydantic==2.10.6
10
+ Requires-Dist: yfinance==0.2.55
11
+ Provides-Extra: dev
12
+ Requires-Dist: pytest-asyncio==0.25.2; extra == 'dev'
13
+ Requires-Dist: pytest==8.3.4; extra == 'dev'
trdr-0.0.1/README.md ADDED
@@ -0,0 +1,190 @@
1
+ # TRDR - Trading Framework
2
+
3
+ TRDR is a framework for algorithmic trading in Python. It features a custom Domain-Specific Language (DSL) for expressing trading strategies in a clear, concise manner.
4
+
5
+ ## 🌟 Features
6
+
7
+ - **Custom DSL**: Define trading strategies with a readable, declarative syntax
8
+ - **Modular Architecture**: Easily swap components like brokers and data providers
9
+ - **Async First**: Built from the ground up with Python's async/await pattern
10
+ - **Mock Trading**: Test strategies with a mock broker before using real money
11
+ - **Telemetry Integration**: Optional OpenTelemetry support for performance monitoring
12
+ - **Pattern Day Trading Controls**: Built-in [PDT rule compliance strategies](src/trdr/core/broker/pdt/README.md) (NunStrategy, WiggleStrategy, YoloStrategy)
13
+
14
+ ## 📦 Installation
15
+
16
+ ```bash
17
+ # Basic installation
18
+ pip install trdr
19
+
20
+ # Development installation (with testing tools)
21
+ pip install -e ".[dev]"
22
+ ```
23
+
24
+ ## 🚀 Quick Start
25
+
26
+ ### 1. Define Your Strategy
27
+
28
+ Create a file `my-strategy.trdr` with your trading strategy:
29
+
30
+ ```
31
+ STRATEGY
32
+ NAME "Moving Average Crossover"
33
+ DESCRIPTION "Basic MA crossover strategy with risk management"
34
+ ENTRY
35
+ ALL_OF
36
+ MA5 CROSSED_ABOVE MA20
37
+ MA20 > MA50
38
+ CURRENT_PRICE > 100
39
+ EXIT
40
+ ANY_OF
41
+ CURRENT_PRICE > (AVERAGE_COST * 1.06) # 6% profit target
42
+ CURRENT_PRICE < (AVERAGE_COST * 0.98) # 2% stop loss
43
+ SIZING
44
+ RULE
45
+ CONDITION
46
+ ALL_OF
47
+ ACCOUNT_EXPOSURE < 0.5
48
+ NUMBER_OF_OPEN_POSITIONS < 3
49
+ DOLLAR_AMOUNT
50
+ (AVAILABLE_CASH * 0.20)
51
+ ```
52
+
53
+ ### 2. Run Your Strategy
54
+
55
+ ```python
56
+ import asyncio
57
+ from trdr.core.bar_provider.yf_bar_provider.yf_bar_provider import YFBarProvider
58
+ from trdr.core.security_provider.security_provider import SecurityProvider
59
+ from trdr.core.broker.mock_broker.mock_broker import MockBroker
60
+ from trdr.core.trading_engine.trading_engine import TradingEngine
61
+ from trdr.core.trading_context.trading_context import TradingContext
62
+ from trdr.core.broker.pdt.nun_strategy import NunStrategy
63
+
64
+ async def main():
65
+ try:
66
+ pdt_strategy = NunStrategy.create()
67
+ async with await MockBroker.create(pdt_strategy=pdt_strategy) as broker:
68
+ bar_provider = await YFBarProvider.create(["TSLA"])
69
+ security_provider = await SecurityProvider.create(bar_provider)
70
+ context = await TradingContext.create(security_provider, broker)
71
+ engine = await TradingEngine.create("my-strategy", context)
72
+ await engine.execute()
73
+ except Exception as e:
74
+ print(e)
75
+
76
+ if __name__ == "__main__":
77
+ asyncio.run(main())
78
+ ```
79
+
80
+ ## 🛠️ Architecture
81
+
82
+ TRDR is built with a modular, component-based architecture:
83
+
84
+ - **Bar Provider**: Supplies price/volume data (Yahoo Finance implementation included)
85
+ - **Security Provider**: Manages available securities for trading
86
+ - **Broker**: Handles order execution
87
+ - [Mock Broker](src/trdr/core/broker/mock_broker/) - Local simulation for testing
88
+ - [Alpaca Broker](src/trdr/core/broker/alpaca_broker/README.md) - Real trading with Alpaca API
89
+ - **Trading Context**: Coordinates components and maintains state
90
+ - **Trading Engine**: Executes strategies using the DSL parser
91
+ - **[PDT Strategies](src/trdr/core/broker/pdt/README.md)**: Enforces Pattern Day Trading rules with multiple compliance strategies
92
+
93
+ ## 📊 DSL Reference
94
+
95
+ The TRDR Domain Specific Language provides a clean (I hope) syntax for expressing trading logic:
96
+
97
+ ### Strategy Structure
98
+
99
+ ```
100
+ STRATEGY
101
+ NAME "Strategy Name"
102
+ DESCRIPTION "Strategy Description"
103
+ ENTRY
104
+ # Entry conditions
105
+ EXIT
106
+ # Exit conditions
107
+ SIZING
108
+ # Position sizing rules
109
+ ```
110
+
111
+ ### Logical Operators
112
+
113
+ ```
114
+ ALL_OF # All conditions must be true
115
+ ANY_OF # Any condition can be true
116
+ ```
117
+
118
+ ### Technical Indicators
119
+
120
+ ```
121
+ MA{period} # Moving average (e.g., MA5, MA20, MA50, MA100, MA200)
122
+ AV{period} # Average volume (e.g., AV5, AV20, AV50, AV100, AV200)
123
+ ```
124
+
125
+ ### Comparison Operators
126
+
127
+ ```
128
+ > # Greater than
129
+ < # Less than
130
+ >= # Greater than or equal to
131
+ <= # Less than or equal to
132
+ == # Equal to
133
+ CROSSED_ABOVE # Indicator crossed above another
134
+ CROSSED_BELOW # Indicator crossed below another
135
+ ```
136
+
137
+ ### Price Metrics
138
+
139
+ ```
140
+ CURRENT_PRICE # Current price of the security
141
+ CURRENT_VOLUME # Current volume of the security
142
+ ```
143
+
144
+ ### Account Metrics
145
+
146
+ ```
147
+ ACCOUNT_EXPOSURE # Percentage of account exposed to market
148
+ AVAILABLE_CASH # Available cash for trading
149
+ AVERAGE_COST # Average cost of current position
150
+ NUMBER_OF_OPEN_POSITIONS # Number of currently open positions
151
+ ```
152
+
153
+ ### Mathematical Operators
154
+
155
+ ```
156
+ + # Addition
157
+ - # Subtraction
158
+ * # Multiplication
159
+ / # Division
160
+ (expression) # Parentheses for grouping expressions
161
+ ```
162
+
163
+ ## 📚 Examples
164
+
165
+ Check the `examples/` directory for complete examples:
166
+
167
+ - **No Telemetry Example**: Basic usage without OpenTelemetry
168
+ - **With Telemetry Example**: Using OpenTelemetry for monitoring
169
+ - **Strategy Examples**: Sample trading strategies
170
+
171
+ ## 🧪 Testing
172
+
173
+ ```bash
174
+ # Run all tests
175
+ pytest
176
+
177
+ # Run specific test file
178
+ pytest src/trdr/path/to/test_file.py
179
+
180
+ # Run specific test
181
+ pytest src/trdr/path/to/test_file.py::TestClass::test_method
182
+ ```
183
+
184
+ ## 📝 License
185
+
186
+ [MIT License](LICENSE)
187
+
188
+ ## 🤝 Contributing
189
+
190
+ Contributions are welcome! Please feel free to submit a Pull Request.
@@ -0,0 +1,28 @@
1
+ # TRDR Examples
2
+
3
+ This directory contains examples demonstrating how to use the TRDR trading framework in different scenarios.
4
+
5
+ ## Examples
6
+
7
+ ### No Telemetry
8
+
9
+ The `no_telemetry` directory demonstrates how to use TRDR without OpenTelemetry integration. This is a simpler setup that doesn't require any tracing infrastructure.
10
+
11
+ **Key features:**
12
+ - Basic usage with MockBroker
13
+ - No telemetry/tracing configuration
14
+ - Yahoo Finance bar provider for historical data
15
+
16
+ ### With Telemetry
17
+
18
+ The `with_telemetry` directory shows how to set up TRDR with OpenTelemetry for distributed tracing and monitoring.
19
+
20
+ **Key features:**
21
+ - OpenTelemetry integration with OTLP exporter
22
+ - MockBroker integration with telemetry
23
+ - Yahoo Finance bar provider for historical data
24
+ - Pattern Day Trading (PDT) strategy integration
25
+
26
+ ## Strategy Examples
27
+
28
+ The `strategies` directory contains example strategy files in TRDR's domain-specific language (DSL).
@@ -0,0 +1,25 @@
1
+ import asyncio
2
+
3
+ from trdr.core.bar_provider.yf_bar_provider.yf_bar_provider import YFBarProvider
4
+ from trdr.core.security_provider.security_provider import SecurityProvider
5
+ from trdr.core.broker.mock_broker.mock_broker import MockBroker
6
+ from trdr.core.trading_engine.trading_engine import TradingEngine
7
+ from trdr.core.trading_context.trading_context import TradingContext
8
+ from trdr.core.broker.pdt.nun_strategy import NunStrategy
9
+
10
+ if __name__ == "__main__":
11
+
12
+ async def main():
13
+ try:
14
+ pdt_strategy = NunStrategy.create()
15
+ async with await MockBroker.create(pdt_strategy=pdt_strategy) as broker:
16
+ bar_provider = await YFBarProvider.create(["TSLA"])
17
+ security_provider = await SecurityProvider.create(bar_provider)
18
+ context = await TradingContext.create(security_provider, broker)
19
+ engine = await TradingEngine.create("first-strat", context, strategies_dir="../strategies")
20
+ await engine.execute()
21
+
22
+ except Exception as e:
23
+ print(e)
24
+
25
+ asyncio.run(main())
@@ -0,0 +1,21 @@
1
+ STRATEGY
2
+ NAME "Basic Strategy"
3
+ DESCRIPTION "Basic testing strategy"
4
+ ENTRY
5
+ ALL_OF
6
+ MA5 CROSSED_ABOVE MA20
7
+ MA20 > MA50
8
+ CURRENT_PRICE > 100
9
+ EXIT
10
+ ANY_OF
11
+ CURRENT_PRICE > (AVERAGE_COST * 1.06)
12
+ CURRENT_PRICE < (AVERAGE_COST * 0.98)
13
+ SIZING
14
+ RULE
15
+ CONDITION
16
+ ALL_OF
17
+ ACCOUNT_EXPOSURE < 0.5
18
+ NUMBER_OF_OPEN_POSITIONS < 3
19
+ DOLLAR_AMOUNT
20
+ (AVAILABLE_CASH * 0.20)
21
+
@@ -0,0 +1,40 @@
1
+ import asyncio
2
+ from opentelemetry import trace
3
+ from opentelemetry.sdk.trace import TracerProvider
4
+ from opentelemetry.sdk.trace.export import BatchSpanProcessor
5
+ from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
6
+
7
+ from trdr.core.bar_provider.yf_bar_provider.yf_bar_provider import YFBarProvider
8
+ from trdr.core.security_provider.security_provider import SecurityProvider
9
+ from trdr.core.broker.mock_broker.mock_broker import MockBroker
10
+ from trdr.core.trading_engine.trading_engine import TradingEngine
11
+ from trdr.core.trading_context.trading_context import TradingContext
12
+ from trdr.core.broker.pdt.nun_strategy import NunStrategy
13
+
14
+ if __name__ == "__main__":
15
+
16
+ async def main():
17
+ tracer_provider = TracerProvider()
18
+ """
19
+ I run the collector as a container locally for testing purposes.
20
+ """
21
+ otlp_exporter = OTLPSpanExporter(endpoint="localhost:4317", insecure=True)
22
+ span_processor = BatchSpanProcessor(otlp_exporter, max_export_batch_size=20)
23
+ tracer_provider.add_span_processor(span_processor)
24
+ trace.set_tracer_provider(tracer_provider)
25
+ tracer = trace.get_tracer("trdr")
26
+ try:
27
+ pdt_strategy = NunStrategy.create(tracer)
28
+ async with await MockBroker.create(pdt_strategy, tracer) as broker:
29
+ bar_provider = await YFBarProvider.create(["TSLA"], tracer)
30
+ security_provider = await SecurityProvider.create(bar_provider, tracer)
31
+ context = await TradingContext.create(security_provider, broker, tracer)
32
+ engine = await TradingEngine.create(
33
+ "first-strat", context, strategies_dir="../strategies", tracer=tracer
34
+ )
35
+ await engine.execute()
36
+
37
+ except Exception as e:
38
+ print(e)
39
+
40
+ asyncio.run(main())
@@ -0,0 +1,28 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "trdr"
7
+ version = "0.0.1"
8
+ authors = [
9
+ { name = "developer_jeb", email = "developer_jeb@outlook.com" },
10
+ ]
11
+ description = "Algorithmic trading library"
12
+ dependencies = [
13
+ "yfinance==0.2.55",
14
+ "aiohttp==3.11.11",
15
+ "opentelemetry-api==1.30.0",
16
+ "opentelemetry-sdk==1.30.0",
17
+ "pydantic==2.10.6",
18
+ ]
19
+
20
+ [project.optional-dependencies]
21
+ dev = [
22
+ "pytest==8.3.4",
23
+ "pytest-asyncio==0.25.2",
24
+ ]
25
+
26
+ [tool.pytest.ini_options]
27
+ pythonpath = ["src"]
28
+ asyncio_default_fixture_loop_scope = "function"
File without changes
File without changes
@@ -0,0 +1,148 @@
1
+ import asyncio
2
+ import pytest
3
+ import yfinance as yf
4
+ import random
5
+ import datetime
6
+
7
+ from .core.security_provider.security_provider import SecurityProvider
8
+ from .core.bar_provider.yf_bar_provider.yf_bar_provider import YFBarProvider
9
+ from .test_utils.fake_yf_download import fake_yf_download
10
+ from .test_utils.security_generator import SecurityGenerator, SecurityCriteria
11
+ from .test_utils.position_generator import PositionGenerator, PositionCriteria
12
+ from .test_utils.order_generator import OrderGenerator, OrderCriteria
13
+ from .core.broker.mock_broker.mock_broker import MockBroker
14
+ from .core.broker.pdt.nun_strategy import NunStrategy
15
+ from .core.broker.pdt.wiggle_strategy import WiggleStrategy
16
+ from .core.broker.pdt.yolo_strategy import YoloStrategy
17
+ from .core.trading_context.trading_context import TradingContext
18
+ from .core.shared.models import TradingDateTime
19
+
20
+
21
+ @pytest.fixture(scope="function")
22
+ def weekday_trading_datetime():
23
+ trading_now = TradingDateTime.now()
24
+ while trading_now.is_weekend:
25
+ trading_now = trading_now + datetime.timedelta(days=1)
26
+ return trading_now
27
+
28
+
29
+ @pytest.fixture(scope="function")
30
+ def weekend_trading_datetime():
31
+ trading_now = TradingDateTime.now()
32
+ while not trading_now.is_weekend:
33
+ trading_now = trading_now + datetime.timedelta(days=1)
34
+ return trading_now
35
+
36
+
37
+ @pytest.fixture(scope="function")
38
+ def yf_bar_provider_with_fake_data(monkeypatch):
39
+ monkeypatch.setattr(yf, "download", fake_yf_download)
40
+ monkeypatch.setattr(yf.shared, "_ERRORS", {"ABCDEFG": "YFTzMissingError()", "AMZN": "JSONDecodeError()"})
41
+ return asyncio.run(YFBarProvider.create(["AAPL", "MSFT", "ABCDEFG", "AMZN"]))
42
+
43
+
44
+ @pytest.fixture(scope="function")
45
+ def security_provider_with_fake_data(yf_bar_provider_with_fake_data):
46
+ return asyncio.run(SecurityProvider.create(yf_bar_provider_with_fake_data))
47
+
48
+
49
+ @pytest.fixture(scope="function")
50
+ def random_security(symbol="AAPL", bar_count=200):
51
+ """Create a random security with the given symbol and bar count.
52
+
53
+ Args:
54
+ symbol: The ticker symbol to use
55
+ count: The number of bars to generate
56
+
57
+ Returns:
58
+ A Security instance with randomly generated price and volume data
59
+ """
60
+ generator = SecurityGenerator(SecurityCriteria(bar_count=bar_count))
61
+ security = generator.find_suitable_security()
62
+ # Override the symbol if requested
63
+ if symbol != security.symbol:
64
+ security.symbol = symbol
65
+ return security
66
+
67
+
68
+ @pytest.fixture(scope="function")
69
+ def get_random_security():
70
+ """Legacy fixture name for backward compatibility."""
71
+ generator = SecurityGenerator(SecurityCriteria(bar_count=200))
72
+ return generator.find_suitable_security()
73
+
74
+
75
+ @pytest.fixture(scope="module")
76
+ def security_generator():
77
+ """Return a configured SecurityGenerator instance."""
78
+ return SecurityGenerator(SecurityCriteria(bar_count=200))
79
+
80
+
81
+ @pytest.fixture(scope="function")
82
+ def short_dummy_position():
83
+ """Create a test position with default values."""
84
+ position = PositionGenerator(criteria=PositionCriteria(bar_count=1, net_position_bias=0)).generate_positions()[0]
85
+ return position
86
+
87
+
88
+ @pytest.fixture(scope="function")
89
+ def long_dummy_position():
90
+ """Create a test position with default values."""
91
+ position = PositionGenerator(criteria=PositionCriteria(bar_count=1, net_position_bias=1)).generate_positions()[0]
92
+ return position
93
+
94
+
95
+ @pytest.fixture(scope="function")
96
+ def dummy_positions():
97
+ """Create a dictionary of test positions."""
98
+ num_positions = random.randint(1, 9)
99
+ positions = PositionGenerator(
100
+ criteria=PositionCriteria(bar_count=num_positions, net_position_bias=0.5)
101
+ ).generate_positions()
102
+ return positions
103
+
104
+
105
+ @pytest.fixture(scope="function")
106
+ def mock_broker_with_nun_strategy():
107
+ nun_strategy = NunStrategy.create()
108
+ broker = asyncio.run(MockBroker.create(pdt_strategy=nun_strategy))
109
+ yield broker
110
+ asyncio.run(broker._session.close())
111
+
112
+
113
+ @pytest.fixture(scope="function")
114
+ def mock_broker_with_wiggle_strategy():
115
+ pdt_strategy = WiggleStrategy.create()
116
+ pdt_strategy.wiggle_room = 2
117
+ broker = asyncio.run(MockBroker.create(pdt_strategy=pdt_strategy))
118
+ yield broker
119
+ asyncio.run(broker._session.close())
120
+
121
+
122
+ @pytest.fixture(scope="function")
123
+ def mock_broker_with_yolo_strategy():
124
+ pdt_strategy = YoloStrategy.create()
125
+ broker = asyncio.run(MockBroker.create(pdt_strategy=pdt_strategy))
126
+ yield broker
127
+ asyncio.run(broker._session.close())
128
+
129
+
130
+ @pytest.fixture(scope="function")
131
+ def mock_trading_context(security_provider_with_fake_data, mock_broker_with_nun_strategy):
132
+ return asyncio.run(TradingContext.create(security_provider_with_fake_data, mock_broker_with_nun_strategy))
133
+
134
+
135
+ @pytest.fixture(scope="function")
136
+ def create_order():
137
+
138
+ def _create_order(symbol: str, side=None):
139
+ return OrderGenerator(criteria=OrderCriteria(count=1, symbol=symbol, side=side)).generate_orders()[0]
140
+
141
+ return _create_order
142
+
143
+
144
+ @pytest.fixture(scope="function")
145
+ def prepared_trading_context(mock_trading_context: TradingContext):
146
+ """Prepare trading context with a valid symbol and security."""
147
+ asyncio.run(mock_trading_context.next_symbol())
148
+ return mock_trading_context
File without changes
File without changes