Change default IQR multiplier to 1.0 for more aggressive outlier filtering
- Change ANALYSIS_IQR_MULTIPLIER default from 1.5 to 1.0 in config.py - Add iqr_multiplier parameter to all filtering & statistics functions - Allow runtime override via MCP tools (get_valuation_comparables, get_deal_statistics) - Update CLAUDE.md docs with new default & override examples Rationale: k=1.0 catches more suspicious deals (e.g. 43% below median) while still preserving legitimate edge cases via hard bounds. Users can override per-call for more conservative filtering (k=1.5) if needed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -873,7 +873,9 @@ class GovmapClient:
|
||||
)
|
||||
|
||||
# Statistics methods (delegate to statistics module)
|
||||
def calculate_deal_statistics(self, deals: List[Deal]) -> DealStatistics:
|
||||
def calculate_deal_statistics(
|
||||
self, deals: List[Deal], iqr_multiplier: Optional[float] = None
|
||||
) -> DealStatistics:
|
||||
"""
|
||||
Calculate statistical aggregations on deal data.
|
||||
|
||||
@@ -881,11 +883,12 @@ class GovmapClient:
|
||||
|
||||
Args:
|
||||
deals: List of Deal model instances
|
||||
iqr_multiplier: Override IQR multiplier for outlier detection (optional)
|
||||
|
||||
Returns:
|
||||
DealStatistics model with comprehensive metrics
|
||||
"""
|
||||
return statistics.calculate_deal_statistics(deals)
|
||||
return statistics.calculate_deal_statistics(deals, iqr_multiplier=iqr_multiplier)
|
||||
|
||||
def _calculate_std_dev(self, values: List[float]) -> float:
|
||||
"""
|
||||
|
||||
@@ -173,7 +173,10 @@ def apply_hard_bounds_deal_amount(
|
||||
|
||||
|
||||
def filter_deals_for_analysis(
|
||||
deals: List[Deal], config: Optional[GovmapConfig] = None, metric: str = "price_per_sqm"
|
||||
deals: List[Deal],
|
||||
config: Optional[GovmapConfig] = None,
|
||||
metric: str = "price_per_sqm",
|
||||
iqr_multiplier: Optional[float] = None,
|
||||
) -> Tuple[List[Deal], Dict[str, Any]]:
|
||||
"""
|
||||
Filter deals to remove outliers based on configuration.
|
||||
@@ -192,6 +195,7 @@ def filter_deals_for_analysis(
|
||||
config: Configuration object (optional, uses global if not provided)
|
||||
metric: Which metric to apply statistical outlier detection to
|
||||
Options: "price_per_sqm", "deal_amount"
|
||||
iqr_multiplier: Override IQR multiplier (optional, uses config value if not provided)
|
||||
|
||||
Returns:
|
||||
Tuple of:
|
||||
@@ -239,6 +243,11 @@ def filter_deals_for_analysis(
|
||||
filters_to_remove[i] = True
|
||||
|
||||
# Step 3: Apply statistical outlier detection to specified metric
|
||||
# Use override value if provided, otherwise use config
|
||||
effective_iqr_multiplier = (
|
||||
iqr_multiplier if iqr_multiplier is not None else config.analysis_iqr_multiplier
|
||||
)
|
||||
|
||||
if config.analysis_outlier_method == "iqr":
|
||||
# Extract values for the specified metric
|
||||
if metric == "price_per_sqm":
|
||||
@@ -260,7 +269,7 @@ def filter_deals_for_analysis(
|
||||
value_indices = []
|
||||
|
||||
if values:
|
||||
statistical_outliers = detect_outliers_iqr(values, config.analysis_iqr_multiplier)
|
||||
statistical_outliers = detect_outliers_iqr(values, effective_iqr_multiplier)
|
||||
for i, is_outlier in enumerate(statistical_outliers):
|
||||
if is_outlier:
|
||||
filters_to_remove[value_indices[i]] = True
|
||||
@@ -302,7 +311,7 @@ def filter_deals_for_analysis(
|
||||
"outlier_indices": outlier_indices,
|
||||
"method_used": config.analysis_outlier_method,
|
||||
"parameters": {
|
||||
"iqr_multiplier": config.analysis_iqr_multiplier
|
||||
"iqr_multiplier": effective_iqr_multiplier
|
||||
if config.analysis_outlier_method == "iqr"
|
||||
else None,
|
||||
"metric": metric,
|
||||
|
||||
@@ -152,7 +152,7 @@ def _calculate_basic_stats(deals: List[Deal]) -> Dict:
|
||||
|
||||
|
||||
def calculate_deal_statistics(
|
||||
deals: List[Deal], config: Optional[GovmapConfig] = None
|
||||
deals: List[Deal], config: Optional[GovmapConfig] = None, iqr_multiplier: Optional[float] = None
|
||||
) -> DealStatistics:
|
||||
"""
|
||||
Calculate statistical aggregations on deal data with optional outlier filtering.
|
||||
@@ -164,6 +164,7 @@ def calculate_deal_statistics(
|
||||
Args:
|
||||
deals: List of Deal model instances
|
||||
config: Configuration object (optional, uses global config if not provided)
|
||||
iqr_multiplier: Override IQR multiplier (optional, uses config value if not provided)
|
||||
|
||||
Returns:
|
||||
DealStatistics model with comprehensive metrics, including:
|
||||
@@ -203,7 +204,7 @@ def calculate_deal_statistics(
|
||||
):
|
||||
# Filter deals for analysis (primarily targeting price_per_sqm outliers)
|
||||
filtered_deals, report_dict = filter_deals_for_analysis(
|
||||
deals, config, metric="price_per_sqm"
|
||||
deals, config, metric="price_per_sqm", iqr_multiplier=iqr_multiplier
|
||||
)
|
||||
|
||||
# Create OutlierReport model
|
||||
|
||||
Reference in New Issue
Block a user