Skip to main content

shape_runtime/
query_result.rs

1//! Enhanced query result types that support both analysis and simulations
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7/// Comprehensive query result that can contain multiple types of output
8#[derive(Debug, Clone)]
9pub struct QueryResult {
10    /// Type of query that was executed
11    pub query_type: QueryType,
12
13    /// Pattern matches if this was a find/scan query
14    pub matches: Option<Vec<PatternMatch>>,
15
16    /// Statistical analysis results
17    pub statistics: Option<StatisticalAnalysis>,
18
19    /// Alert results
20    pub alert: Option<AlertResult>,
21
22    /// Raw value result
23    pub value: Option<shape_value::ValueWord>,
24
25    /// Combined summary metrics
26    pub summary: Option<SummaryMetrics>,
27
28    /// Raw data for custom visualization
29    pub data: Option<QueryData>,
30
31    /// Execution metadata
32    pub metadata: QueryMetadata,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub enum QueryType {
37    Find,
38    Scan,
39    Analyze,
40    Simulate,
41    Alert,
42    Value,
43    With,
44    Backtest,
45}
46
47/// Statistical analysis of patterns or conditions
48#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct StatisticalAnalysis {
50    /// Total occurrences of the pattern/condition
51    pub total_occurrences: usize,
52
53    /// Success rate (however defined by the query)
54    pub success_rate: f64,
55
56    /// Distribution of outcomes
57    pub outcome_distribution: HashMap<String, f64>,
58
59    /// Time-based statistics
60    pub time_stats: TimeStatistics,
61
62    /// Magnitude statistics (generic value analysis)
63    pub magnitude_stats: MagnitudeStatistics,
64
65    /// Custom metrics defined by the query
66    pub custom_metrics: HashMap<String, f64>,
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct TimeStatistics {
71    /// Average time to outcome
72    pub avg_time_to_outcome: f64,
73
74    /// Distribution by hour of day
75    pub hourly_distribution: Vec<HourlyStats>,
76
77    /// Distribution by day of week
78    pub daily_distribution: Vec<DailyStats>,
79
80    /// Seasonality metrics
81    pub seasonality: Option<SeasonalityMetrics>,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct HourlyStats {
86    pub hour: u8,
87    pub occurrences: usize,
88    pub success_rate: f64,
89    pub avg_magnitude: f64,
90}
91
92#[derive(Debug, Clone, Serialize, Deserialize)]
93pub struct DailyStats {
94    pub day: String,
95    pub occurrences: usize,
96    pub success_rate: f64,
97    pub avg_magnitude: f64,
98}
99
100#[derive(Debug, Clone, Serialize, Deserialize)]
101pub struct SeasonalityMetrics {
102    pub monthly_pattern: Vec<f64>,
103    pub quarterly_pattern: Vec<f64>,
104    pub yearly_trend: Vec<f64>,
105}
106
107#[derive(Debug, Clone, Serialize, Deserialize)]
108pub struct MagnitudeStatistics {
109    pub average: f64,
110    pub median: f64,
111    pub std_dev: f64,
112    pub min: f64,
113    pub max: f64,
114    pub percentiles: HashMap<String, f64>, // "p25", "p75", "p95", etc.
115}
116
117/// Alert result
118#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct AlertResult {
120    pub id: String,
121    pub active: bool,
122    pub message: String,
123    pub level: String,
124    pub timestamp: DateTime<Utc>,
125}
126
127/// Combined summary metrics for quick overview
128#[derive(Debug, Clone, Serialize, Deserialize)]
129pub struct SummaryMetrics {
130    /// Key statistical findings
131    pub pattern_frequency: f64, // frequency relative to data points
132    pub pattern_reliability: f64, // success rate
133
134    /// Combined score
135    pub confidence_score: f64, // 0-100
136
137    /// Generic value analysis
138    pub average_outcome: f64,
139    pub expectancy: f64,
140}
141
142/// Raw data for custom analysis/visualization
143#[derive(Debug, Clone, Serialize, Deserialize)]
144pub struct QueryData {
145    /// Time series data
146    pub time_series: Vec<TimeSeriesPoint>,
147
148    /// Distribution data
149    pub distributions: HashMap<String, Vec<f64>>,
150
151    /// Correlation matrices
152    pub correlations: HashMap<String, Vec<Vec<f64>>>,
153
154    /// Custom data tables
155    pub tables: HashMap<String, DataTable>,
156}
157
158#[derive(Debug, Clone, Serialize, Deserialize)]
159pub struct TimeSeriesPoint {
160    pub timestamp: DateTime<Utc>,
161    pub values: HashMap<String, f64>,
162}
163
164#[derive(Debug, Clone, Serialize, Deserialize)]
165pub struct DataTable {
166    pub columns: Vec<String>,
167    pub rows: Vec<Vec<serde_json::Value>>,
168}
169
170/// Query execution metadata
171#[derive(Debug, Clone, Serialize, Deserialize)]
172pub struct QueryMetadata {
173    pub execution_time_ms: u64,
174    pub data_points_analyzed: usize,
175    pub timeframe: String,
176    pub id: String,
177    pub date_range: (DateTime<Utc>, DateTime<Utc>),
178    pub query_hash: String, // for caching
179    pub warnings: Vec<String>,
180}
181
182/// Pattern match with enhanced information
183#[derive(Debug, Clone, Serialize, Deserialize)]
184pub struct PatternMatch {
185    pub pattern_name: String,
186    pub index: usize,
187    pub timestamp: DateTime<Utc>,
188    pub confidence: f64,
189    pub id: String,
190    pub metadata: serde_json::Value,
191}
192
193impl QueryResult {
194    /// Create a new empty result
195    pub fn new(query_type: QueryType, id: String, timeframe: String) -> Self {
196        Self {
197            query_type,
198            matches: None,
199            statistics: None,
200            alert: None,
201            value: None,
202            summary: None,
203            data: None,
204            metadata: QueryMetadata {
205                execution_time_ms: 0,
206                data_points_analyzed: 0,
207                timeframe,
208                id,
209                date_range: (Utc::now(), Utc::now()),
210                query_hash: String::new(),
211                warnings: Vec::new(),
212            },
213        }
214    }
215
216    /// Add statistical analysis results
217    pub fn with_statistics(mut self, stats: StatisticalAnalysis) -> Self {
218        self.statistics = Some(stats);
219        self
220    }
221
222    /// Add alert results
223    pub fn with_alert(mut self, alert: AlertResult) -> Self {
224        self.alert = Some(alert);
225        self
226    }
227
228    /// Add value result
229    pub fn with_value(mut self, value: shape_value::ValueWord) -> Self {
230        self.value = Some(value);
231        self
232    }
233
234    /// Calculate and add summary metrics
235    pub fn calculate_summary(&mut self) {
236        let mut summary = SummaryMetrics {
237            pattern_frequency: 0.0,
238            pattern_reliability: 0.0,
239            confidence_score: 0.0,
240            average_outcome: 0.0,
241            expectancy: 0.0,
242        };
243
244        // Calculate from statistics
245        if let Some(ref stats) = self.statistics {
246            summary.pattern_frequency = if self.metadata.data_points_analyzed > 0 {
247                stats.total_occurrences as f64 / self.metadata.data_points_analyzed as f64
248            } else {
249                0.0
250            };
251            summary.pattern_reliability = stats.success_rate;
252            summary.average_outcome = stats.magnitude_stats.average;
253            summary.expectancy = stats.success_rate * stats.magnitude_stats.average;
254        }
255
256        // Overall confidence score (0-100)
257        summary.confidence_score = calculate_confidence_score(&summary, &self.statistics);
258
259        self.summary = Some(summary);
260    }
261
262    /// Format summary as a human-readable string
263    pub fn format_summary(&self) -> String {
264        if let Some(ref summary) = self.summary {
265            format!(
266                "Frequency: {:.4}, Reliability: {:.2}%, Confidence: {:.1}/100",
267                summary.pattern_frequency,
268                summary.pattern_reliability * 100.0,
269                summary.confidence_score
270            )
271        } else {
272            "No summary available".to_string()
273        }
274    }
275}
276
277/// Calculate a confidence score based on various metrics
278fn calculate_confidence_score(
279    _summary: &SummaryMetrics,
280    stats: &Option<StatisticalAnalysis>,
281) -> f64 {
282    let mut score: f64 = 50.0; // Start neutral
283
284    // Statistical confidence
285    if let Some(stats) = stats {
286        if stats.total_occurrences > 100 {
287            score += 10.0; // Good sample size
288        }
289        if stats.success_rate > 0.6 {
290            score += 10.0;
291        }
292    }
293
294    score.clamp(0.0, 100.0)
295}