Skip to content

Commit df94949

Browse files
authored
Merge pull request #60 from TexasCoding:v3.5.0_multi_instruments
feat: Multi-Instrument TradingSuite Implementation
2 parents 6cf8032 + bf93a88 commit df94949

36 files changed

+3235
-545
lines changed

.cursor/mcp.json

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{
2+
"mcpServers": {
3+
"desktop-commander": {
4+
"command": "npx",
5+
"args": [
6+
"-y",
7+
"@wonderwhy-er/desktop-commander"
8+
]
9+
},
10+
"github": {
11+
"command": "npx",
12+
"args": [
13+
"-y",
14+
"@modelcontextprotocol/server-github"
15+
],
16+
"env": {
17+
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}"
18+
}
19+
},
20+
"project-x-py Docs": {
21+
"command": "npx",
22+
"args": [
23+
"mcp-remote",
24+
"https://gitmcp.io/TexasCoding/project-x-py"
25+
]
26+
},
27+
"mcp-obsidian": {
28+
"command": "uvx",
29+
"args": [
30+
"mcp-obsidian"
31+
],
32+
"env": {
33+
"OBSIDIAN_HOST": "127.0.0.1",
34+
"OBSIDIAN_PORT": "27124",
35+
"OBSIDIAN_API_KEY": "${OBSIDIAN_API_KEY}"
36+
}
37+
},
38+
"tavily-mcp": {
39+
"command": "npx",
40+
"args": [
41+
"-y",
42+
"tavily-mcp@latest"
43+
],
44+
"env": {
45+
"TAVILY_API_KEY": "${TAVILY_API_KEY}"
46+
}
47+
},
48+
"graphiti-memory": {
49+
"transport": "stdio",
50+
"command": "/Users/jeffreywest/.local/bin/uv",
51+
"args": [
52+
"run",
53+
"--directory",
54+
"/Users/jeffreywest/graphiti/mcp_server",
55+
"graphiti_mcp_server.py",
56+
"--transport",
57+
"stdio"
58+
]
59+
}
60+
}
61+
}

.cursor/rules/README.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# ProjectX SDK Development Rules
2+
3+
This directory contains precise, focused development rules for the ProjectX Python SDK. Each rule file covers a specific aspect of development and must be followed strictly.
4+
5+
## Rule Files Overview
6+
7+
### 🔴 [TDD Core Rules](./tdd_core.md)
8+
**CRITICAL**: Test-Driven Development enforcement
9+
- RED-GREEN-REFACTOR cycle requirements
10+
- Test-first development mandates
11+
- Tests as source of truth principles
12+
- Bug fix and refactoring processes
13+
14+
### [Async Testing Rules](./async_testing.md)
15+
**CRITICAL**: Async-first testing patterns
16+
- @pytest.mark.asyncio requirements
17+
- Async context manager testing
18+
- WebSocket testing patterns
19+
- Async performance and memory testing
20+
21+
### 🔍 [Code Quality Rules](./code_quality.md)
22+
**CRITICAL**: Quality standards and validation
23+
- Modern type hints (Python 3.10+)
24+
- Error handling patterns
25+
- Polars-only DataFrame operations
26+
- Memory management requirements
27+
28+
### 🔄 [Development Workflow](./development_workflow.md)
29+
**CRITICAL**: Development process enforcement
30+
- TDD cycle workflow
31+
- Quality gate requirements
32+
- Testing execution standards
33+
- Release and debugging workflows
34+
35+
## Rule Priority
36+
37+
**All rules are MANDATORY**. Priority for conflicts:
38+
39+
1. **TDD Core Rules** - Fundamental development methodology
40+
2. **Async Testing Rules** - SDK-specific async requirements
41+
3. **Code Quality Rules** - Technical implementation standards
42+
4. **Development Workflow** - Process and automation
43+
44+
## Quick Reference
45+
46+
### TDD Cycle (MANDATORY)
47+
```bash
48+
# 1. RED: Write failing test
49+
./test.sh tests/test_new_feature.py # MUST FAIL
50+
51+
# 2. GREEN: Minimal implementation
52+
./test.sh tests/test_new_feature.py # MUST PASS
53+
54+
# 3. REFACTOR: Improve while keeping tests green
55+
./test.sh # ALL tests must pass
56+
```
57+
58+
### Quality Gates (MANDATORY)
59+
```bash
60+
uv run mypy src/ # Type checking
61+
uv run ruff check . --fix # Linting
62+
uv run ruff format . # Formatting
63+
./test.sh # Full test suite
64+
```
65+
66+
### Async Test Pattern (MANDATORY)
67+
```python
68+
@pytest.mark.asyncio
69+
async def test_expected_behavior():
70+
# Test async functionality correctly
71+
pass
72+
```
73+
74+
## Enforcement
75+
76+
These rules are enforced through:
77+
- Cursor AI assistant guidance
78+
- Pre-commit hooks (when available)
79+
- Code review checklists
80+
- CI/CD pipeline checks
81+
- Memory tracking of violations
82+
83+
## Rule Updates
84+
85+
When updating rules:
86+
1. Follow TDD to write tests for rule enforcement
87+
2. Update relevant rule files
88+
3. Update this README if structure changes
89+
4. Document changes in memory for team awareness
90+
91+
## Violations
92+
93+
Rule violations are **NEVER acceptable**:
94+
- ❌ Writing implementation before tests
95+
- ❌ Using legacy type syntax
96+
- ❌ Missing async decorators
97+
- ❌ Skipping quality gates
98+
- ❌ Any pattern marked as FORBIDDEN in rule files
99+
100+
**Remember: These rules ensure SDK quality and maintainability. No exceptions.**

.cursor/rules/async_testing.md

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
# Async Testing Rules for ProjectX SDK
2+
3+
**CRITICAL**: This SDK is 100% async-first. All testing must follow async patterns correctly.
4+
5+
## Async Test Requirements
6+
7+
### 1. Async Test Decorators (MANDATORY)
8+
9+
**ALWAYS use for async test methods:**
10+
```python
11+
import pytest
12+
13+
@pytest.mark.asyncio
14+
async def test_async_method():
15+
# Test implementation
16+
pass
17+
```
18+
19+
**FORBIDDEN patterns:**
20+
```python
21+
# ❌ WRONG: Missing @pytest.mark.asyncio
22+
async def test_async_method():
23+
pass
24+
25+
# ❌ WRONG: Using sync test for async code
26+
def test_async_method():
27+
result = asyncio.run(async_method())
28+
```
29+
30+
### 2. Async Context Manager Testing
31+
32+
**ALWAYS test async context managers properly:**
33+
```python
34+
@pytest.mark.asyncio
35+
async def test_projectx_client_context_manager():
36+
async with ProjectX.from_env() as client:
37+
await client.authenticate()
38+
# Test within context
39+
assert client.is_authenticated
40+
# Test cleanup happened
41+
```
42+
43+
### 3. Async Mock Patterns
44+
45+
**Use aioresponses for HTTP mocking:**
46+
```python
47+
from aioresponses import aioresponses
48+
import pytest
49+
50+
@pytest.mark.asyncio
51+
async def test_api_call():
52+
with aioresponses() as m:
53+
m.get("https://api.example.com/data", payload={"result": "success"})
54+
55+
async with ProjectX.from_env() as client:
56+
result = await client.get_data()
57+
assert result["result"] == "success"
58+
```
59+
60+
**Use AsyncMock for async methods:**
61+
```python
62+
from unittest.mock import AsyncMock
63+
import pytest
64+
65+
@pytest.mark.asyncio
66+
async def test_realtime_callback():
67+
callback = AsyncMock()
68+
manager = RealtimeDataManager(callback=callback)
69+
70+
await manager.process_tick({"price": 100.0})
71+
72+
callback.assert_called_once_with({"price": 100.0})
73+
```
74+
75+
### 4. WebSocket Testing Patterns
76+
77+
**Test WebSocket connections with proper async handling:**
78+
```python
79+
@pytest.mark.asyncio
80+
async def test_websocket_connection():
81+
async with create_realtime_client("token", "account") as client:
82+
await client.connect()
83+
assert client.is_connected
84+
85+
await client.subscribe("MNQ")
86+
# Test subscription
87+
```
88+
89+
### 5. Async Error Handling Tests
90+
91+
**Test async exceptions properly:**
92+
```python
93+
@pytest.mark.asyncio
94+
async def test_api_error_handling():
95+
with aioresponses() as m:
96+
m.get("https://api.example.com/data", status=500)
97+
98+
async with ProjectX.from_env() as client:
99+
with pytest.raises(ProjectXAPIError):
100+
await client.get_data()
101+
```
102+
103+
## Async Test Organization
104+
105+
### 6. Test File Structure
106+
107+
**Organize async tests by component:**
108+
```
109+
tests/
110+
├── unit/
111+
│ ├── test_async_client.py # Client async tests
112+
│ ├── test_async_order_manager.py # OrderManager async tests
113+
│ └── test_async_realtime.py # Realtime async tests
114+
├── integration/
115+
│ └── test_async_integration.py # Cross-component async tests
116+
└── e2e/
117+
└── test_async_e2e.py # End-to-end async tests
118+
```
119+
120+
### 7. Async Test Fixtures
121+
122+
**Create reusable async fixtures:**
123+
```python
124+
@pytest_asyncio.fixture
125+
async def authenticated_client():
126+
async with ProjectX.from_env() as client:
127+
await client.authenticate()
128+
yield client
129+
130+
@pytest_asyncio.fixture
131+
async def realtime_client(authenticated_client):
132+
client = await create_realtime_client(
133+
authenticated_client.jwt_token,
134+
str(authenticated_client.account_id)
135+
)
136+
yield client
137+
await client.close()
138+
```
139+
140+
## Performance Testing for Async Code
141+
142+
### 8. Async Performance Tests
143+
144+
**Test async performance characteristics:**
145+
```python
146+
@pytest.mark.asyncio
147+
async def test_concurrent_requests():
148+
async with ProjectX.from_env() as client:
149+
await client.authenticate()
150+
151+
# Test concurrent execution
152+
tasks = [
153+
client.get_bars("MNQ", days=1),
154+
client.get_bars("ES", days=1),
155+
client.get_bars("RTY", days=1)
156+
]
157+
158+
start_time = time.time()
159+
results = await asyncio.gather(*tasks)
160+
duration = time.time() - start_time
161+
162+
assert len(results) == 3
163+
assert duration < 5.0 # Should be faster than sequential
164+
```
165+
166+
### 9. Memory Leak Testing
167+
168+
**Test for async memory leaks:**
169+
```python
170+
@pytest.mark.asyncio
171+
async def test_no_memory_leaks():
172+
import gc
173+
import tracemalloc
174+
175+
tracemalloc.start()
176+
177+
for _ in range(100):
178+
async with ProjectX.from_env() as client:
179+
await client.authenticate()
180+
await client.get_bars("MNQ", days=1)
181+
182+
gc.collect()
183+
current, peak = tracemalloc.get_traced_memory()
184+
tracemalloc.stop()
185+
186+
# Memory should not grow unbounded
187+
assert current < peak * 1.1
188+
```
189+
190+
## Critical Async Testing Violations
191+
192+
**These are NEVER acceptable:**
193+
194+
**Using sync tests for async code**
195+
**Missing @pytest.mark.asyncio decorator**
196+
**Using asyncio.run() in test methods**
197+
**Blocking async code with .result() or similar**
198+
**Not properly cleaning up async resources**
199+
**Testing async code synchronously**
200+
**Ignoring async context manager lifecycle**
201+
202+
## Async Test Execution
203+
204+
**Use proper test execution:**
205+
```bash
206+
# ✅ CORRECT: Use test.sh for proper environment
207+
./test.sh tests/test_async_client.py
208+
209+
# ✅ CORRECT: Run specific async tests
210+
uv run pytest -k "async" tests/
211+
212+
# ✅ CORRECT: Run with asyncio mode
213+
uv run pytest --asyncio-mode=auto tests/
214+
```
215+
216+
## Required Dependencies
217+
218+
**Ensure these are in test dependencies:**
219+
```toml
220+
[project.optional-dependencies]
221+
dev = [
222+
"pytest-asyncio>=0.21.0",
223+
"aioresponses>=0.7.4",
224+
"pytest>=7.0.0",
225+
]
226+
```
227+
228+
Remember: **Async code requires async tests. No exceptions.**

0 commit comments

Comments
 (0)