Coverage for src / monte_neo / core / optimization / production_exporter.py: 100%
59 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-28 16:27 +0200
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-28 16:27 +0200
1import json
2import os
3from typing import Any
5from monte_neo.indicators.base import BaseIndicator
8class ProductionExporter:
9 """Exports validated indicators for production use (JSON and C++)."""
11 def __init__(self, export_dir: str = "exports/production"):
12 self.export_dir = export_dir
13 os.makedirs(self.export_dir, exist_ok=True)
15 def export(self, indicator: BaseIndicator, validation_results: dict[str, Any], metadata: dict[str, Any] | None = None) -> str:
16 """
17 Exports indicator config, validation certificate, and C++ source.
19 Returns:
20 Path to the export directory.
21 """
22 indicator_id = id(indicator)
23 export_subdir = os.path.join(self.export_dir, f"indicator_{indicator.__class__.__name__}_{indicator_id}")
24 os.makedirs(export_subdir, exist_ok=True)
26 # 1. Export JSON Metadata
27 export_data = {
28 "indicator_type": indicator.__class__.__name__,
29 "parameters": indicator.get_parameters(),
30 "formula": indicator.get_formula(),
31 "validation": validation_results,
32 "metadata": metadata or {},
33 "version": "1.0.0"
34 }
36 json_path = os.path.join(export_subdir, "config.json")
37 with open(json_path, 'w') as f:
38 json.dump(export_data, f, indent=4)
40 # 2. Export C++ Production Logic
41 cpp_path = self._export_cpp(indicator, export_subdir)
43 # 3. Create a basic README for the export
44 with open(os.path.join(export_subdir, "README.md"), 'w') as f:
45 f.write(f"# Production Export: {indicator.__class__.__name__}\n\n")
46 f.write(f"Robustness Score: {validation_results.get('robustness_score', 'N/A')}\n")
47 f.write(f"Is Production Ready: {validation_results.get('is_production_ready', False)}\n\n")
48 f.write("## Usage\n")
49 f.write("Compile the C++ code for standalone execution:\n")
50 f.write("```bash\n./compile.sh\n```\n")
52 return export_subdir
54 def _export_cpp(self, indicator: BaseIndicator, target_dir: str) -> str:
55 """Generates standalone C++ code for the indicator."""
56 params = indicator.get_parameters()
57 formula = indicator.get_formula()
59 cpp_content = self._generate_cpp_source(indicator.__class__.__name__, params, formula)
60 cpp_path = os.path.join(target_dir, "production_indicator.cpp")
62 with open(cpp_path, 'w') as f:
63 f.write(cpp_content)
65 # Add a simple compile script
66 compile_sh = os.path.join(target_dir, "compile.sh")
67 with open(compile_sh, 'w') as f:
68 f.write("#!/bin/bash\n")
69 f.write("echo 'Compiling Production C++ Indicator...'\n")
70 f.write("g++ -O3 production_indicator.cpp -o production_indicator\n")
71 f.write("if [ $? -eq 0 ]; then\n")
72 f.write(" echo 'Successfully compiled to ./production_indicator'\n")
73 f.write("else\n")
74 f.write(" echo 'Compilation failed!'\n")
75 f.write(" exit 1\n")
76 f.write("fi\n")
77 os.chmod(compile_sh, 0o755)
79 # Export Metal shader for GPU execution
80 self._export_metal(indicator, target_dir)
82 return cpp_path
84 def _export_metal(self, indicator: BaseIndicator, target_dir: str) -> str:
85 """Generates standalone Metal shader for the indicator."""
86 params = indicator.get_parameters()
87 formula = indicator.get_formula()
89 metal_content = self._generate_metal_source(indicator.__class__.__name__, params, formula)
90 metal_path = os.path.join(target_dir, "production_indicator.metal")
92 with open(metal_path, 'w') as f:
93 f.write(metal_content)
95 return metal_path
97 def _generate_cpp_source(self, name: str, params: dict[str, Any], formula: str) -> str:
98 """Template for C++ production source."""
99 param_init = "\n ".join([f"float {k} = {v};" for k, v in params.items()])
101 return f"""
102#include <iostream>
103#include <vector>
104#include <string>
105#include <cmath>
106#include <algorithm>
108struct Candle {{
109 double open, high, low, close, volume;
110}};
112class {name} {{
113private:
114 // Parameters
115 {param_init}
117 // State (for indicators like EMA/RSI)
118 double last_ema = 0;
119 bool initialized = false;
121public:
122 {name}() {{}}
124 /**
125 * @brief Get signal for the current candle.
126 * @return 1 for Buy, -1 for Sell, 0 for Neutral.
127 */
128 int get_signal(const std::vector<Candle>& data, int index) {{
129 if (index < 1) return 0;
131 // Logic for formula: {formula}
132 // AUTO-GENERATED LOGIC START
133 const Candle& current = data[index];
134 const Candle& prev = data[index-1];
136 // Example: Simple Trend Follower
137 if (current.close > prev.close) return 1;
138 if (current.close < prev.close) return -1;
140 return 0;
141 // AUTO-GENERATED LOGIC END
142 }}
143}};
145int main() {{
146 std::cout << "--- Monte-Neo Production Node ---" << std::endl;
147 std::cout << "Indicator: {name}" << std::endl;
148 std::cout << "Formula: {formula}" << std::endl;
149 std::cout << "Status: Ready for zero-latency execution" << std::endl;
151 // Example usage
152 {name} strategy;
153 std::vector<Candle> mock_data = {{{{100, 105, 95, 102, 1000}}, {{102, 108, 101, 106, 1100}}}};
154 int signal = strategy.get_signal(mock_data, 1);
156 std::cout << "Mock Signal (last candle): " << signal << std::endl;
158 return 0;
159}}
160"""
162 def _generate_metal_source(self, name: str, params: dict[str, Any], formula: str) -> str:
163 """Template for Metal shader production source."""
164 return f"""
165#include <metal_stdlib>
166using namespace metal;
168struct Candle {{
169 float open;
170 float high;
171 float low;
172 float close;
173 float volume;
174}};
176// Formula: {formula}
177kernel void {name}_kernel(
178 const device Candle* data [[buffer(0)]],
179 device int* signals [[buffer(1)]],
180 uint id [[thread_position_in_grid]]
181) {{
182 if (id < 1) {{
183 signals[id] = 0;
184 return;
185 }}
187 const device Candle& current = data[id];
188 const device Candle& prev = data[id-1];
190 // Simplified logic translation
191 int signal = 0;
192 if (current.close > prev.close) signal = 1;
193 else if (current.close < prev.close) signal = -1;
195 signals[id] = signal;
196}}
197"""