-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmulti_file.py
More file actions
276 lines (213 loc) · 7.95 KB
/
Copy pathmulti_file.py
File metadata and controls
276 lines (213 loc) · 7.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
"""Multi-file code generation for QuantConnect projects."""
from pathlib import Path
from typing import Dict, List, Optional
from dataclasses import dataclass, field
import logging
logger = logging.getLogger(__name__)
@dataclass
class CodeFile:
"""Represents a generated code file."""
filename: str
content: str
dependencies: List[str] = field(default_factory=list)
description: str = ""
@dataclass
class ProjectStructure:
"""Complete project structure with all files."""
name: str
files: Dict[str, CodeFile]
base_path: Optional[Path] = None
def get_file(self, filename: str) -> Optional[CodeFile]:
"""Get a specific file."""
return self.files.get(filename)
def add_file(self, file: CodeFile):
"""Add a file to the project."""
self.files[file.filename] = file
def list_files(self) -> List[str]:
"""List all filenames."""
return list(self.files.keys())
class MultiFileGenerator:
"""Generate multi-file QuantConnect projects."""
def __init__(self, project_name: str):
"""
Initialize generator.
Args:
project_name: Name of the project
"""
self.project_name = project_name
self.structure = ProjectStructure(
name=project_name,
files={}
)
self.logger = logging.getLogger(f"quantcoder.{self.__class__.__name__}")
def add_file(
self,
filename: str,
content: str,
dependencies: List[str] = None,
description: str = ""
):
"""
Add a file to the project.
Args:
filename: File name (e.g., "Main.py")
content: File content
dependencies: List of files this depends on
description: File description
"""
file = CodeFile(
filename=filename,
content=content,
dependencies=dependencies or [],
description=description
)
self.structure.add_file(file)
self.logger.info(f"Added file: {filename}")
def generate_project_structure(
self,
base_path: Path,
create_readme: bool = True,
create_init: bool = True
) -> Path:
"""
Generate complete project directory.
Args:
base_path: Base directory path
create_readme: Whether to create README.md
create_init: Whether to create __init__.py
Returns:
Path to created project directory
"""
project_dir = base_path / self.project_name
project_dir.mkdir(exist_ok=True, parents=True)
self.logger.info(f"Generating project at: {project_dir}")
# Write all files
for filename, file in self.structure.files.items():
file_path = project_dir / filename
file_path.write_text(file.content, encoding='utf-8')
self.logger.info(f" Created: {filename}")
# Generate __init__.py
if create_init and not self.structure.get_file("__init__.py"):
init_content = self._generate_init_file()
(project_dir / "__init__.py").write_text(init_content)
self.logger.info(" Created: __init__.py")
# Generate README
if create_readme and not self.structure.get_file("README.md"):
readme_content = self._generate_readme()
(project_dir / "README.md").write_text(readme_content)
self.logger.info(" Created: README.md")
# Generate requirements.txt
requirements_content = self._generate_requirements()
(project_dir / "requirements.txt").write_text(requirements_content)
self.logger.info(" Created: requirements.txt")
self.structure.base_path = project_dir
self.logger.info(f"✓ Project generated successfully: {project_dir}")
return project_dir
def _generate_init_file(self) -> str:
"""Generate __init__.py with imports."""
imports = []
# Import all modules except Main.py
for filename in self.structure.files.keys():
if filename.endswith('.py') and filename not in ['Main.py', '__init__.py']:
module = filename[:-3] # Remove .py
imports.append(f"from .{module} import *")
if not imports:
imports = ["# No modules to import"]
header = f'''"""
{self.project_name}
Generated by QuantCoder CLI v3.0 - Multi-Agent System
"""
'''
return header + "\n".join(imports) + "\n"
def _generate_readme(self) -> str:
"""Generate README.md."""
files_list = "\n".join(
f"- **{f}**: {self._describe_file(f)}"
for f in sorted(self.structure.files.keys())
)
return f"""# {self.project_name}
> Generated by QuantCoder CLI v3.0 - Multi-Agent System
## 📁 Project Structure
{files_list}
## 🚀 Usage
### In QuantConnect
1. Upload this directory to QuantConnect
2. Set `Main.py` as the entry point
3. Run backtest
### Locally
```bash
# Install dependencies
pip install -r requirements.txt
# The algorithm uses QuantConnect's Framework:
# - Universe selection in Universe.py
# - Alpha signals in Alpha.py
# - Risk management in Risk.py
# - Main coordination in Main.py
```
## 📊 Algorithm Architecture
This algorithm follows QuantConnect's modular Framework architecture:
```
Main.py (Entry Point)
├─> Universe.py (Stock Selection)
├─> Alpha.py (Signal Generation)
├─> Risk.py (Risk Management)
└─> Portfolio Construction & Execution
```
## ⚙️ Configuration
Key parameters can be adjusted in `Main.py`:
- **Start/End Dates**: Algorithm backtest period
- **Initial Cash**: Starting capital
- **Universe**: Stock selection criteria
- **Alpha**: Signal generation logic
- **Risk**: Position sizing and risk controls
## 📚 Learn More
- [QuantConnect Documentation](https://www.quantconnect.com/docs/)
- [Algorithm Framework](https://www.quantconnect.com/docs/v2/writing-algorithms/algorithm-framework)
---
*Generated with QuantCoder CLI - https://github.com/SL-Mar/quantcoder-cli*
"""
def _generate_requirements(self) -> str:
"""Generate requirements.txt."""
return """# QuantConnect Dependencies
# These are provided by QuantConnect Cloud
# For local development:
# quantconnect-stubs>=1.0.0
# Note: Most dependencies are pre-installed in QuantConnect environment
"""
def _describe_file(self, filename: str) -> str:
"""Describe file purpose."""
file = self.structure.get_file(filename)
if file and file.description:
return file.description
descriptions = {
"Main.py": "Main algorithm entry point and coordinator",
"Universe.py": "Universe selection model (stock screening)",
"Alpha.py": "Alpha model (trading signal generation)",
"Risk.py": "Risk management model (position sizing, stops)",
"Portfolio.py": "Portfolio construction model",
"__init__.py": "Package initialization",
"README.md": "Project documentation",
"requirements.txt": "Python dependencies",
}
return descriptions.get(filename, "Supporting module")
def get_file_tree(self) -> str:
"""Get ASCII file tree representation."""
lines = [f"{self.project_name}/"]
files = sorted(self.structure.files.keys())
for i, filename in enumerate(files):
is_last = i == len(files) - 1
prefix = "└── " if is_last else "├── "
lines.append(f"{prefix}{filename}")
return "\n".join(lines)
def get_summary(self) -> Dict:
"""Get project summary."""
total_lines = sum(
len(file.content.split('\n'))
for file in self.structure.files.values()
)
return {
"project_name": self.project_name,
"total_files": len(self.structure.files),
"total_lines": total_lines,
"files": list(self.structure.files.keys())
}