The Analytics module provides access to market data insights and statistical information in the WFRMLS system. This includes market trends, pricing analytics, inventory statistics, and performance metrics.
The AnalyticsService class handles all analytics-related operations through the WFRMLS API. Analytics provide aggregated data and insights for market analysis, reporting, and business intelligence.
# Get recent market analyticsrecent_analytics=client.analytics.get_analytics(filter_query="AnalyticsDate ge 2024-01-01T00:00:00Z",select=["AnalyticsKey","AnalyticsDate","MarketArea","MedianPrice","InventoryCount"],orderby="AnalyticsDate desc",top=100)# Get analytics for specific market areaarea_analytics=client.analytics.get_analytics(filter_query="MarketArea eq 'Salt Lake County'",orderby="AnalyticsDate desc")# Get price trend dataprice_trends=client.analytics.get_analytics(filter_query="AnalyticsType eq 'PriceTrend'",select=["AnalyticsDate","MarketArea","MedianPrice","AveragePrice"])
# Get complete analytics recordanalytic=client.analytics.get_analytic("ANALYTICS123")# Get specific fields onlyprice_data=client.analytics.get_analytic("ANALYTICS123",select=["AnalyticsDate","MarketArea","MedianPrice","AveragePrice","InventoryCount"])
fromdatetimeimportdatetime,timedelta# Get 12 months of market data for trend analysisstart_date=datetime.now()-timedelta(days=365)market_trends=client.analytics.get_analytics(filter_query=f"AnalyticsDate ge {start_date.isoformat()}Z and AnalyticsType eq 'MarketSummary'",select=["AnalyticsDate","MarketArea","MedianPrice","AveragePrice","InventoryCount","DaysOnMarket","SalesVolume"],orderby="AnalyticsDate asc")# Calculate price appreciationprice_data={}forrecordinmarket_trends:area=record['MarketArea']ifareanotinprice_data:price_data[area]=[]price_data[area].append({'date':record['AnalyticsDate'],'median_price':record['MedianPrice']})forarea,datainprice_data.items():iflen(data)>=2:latest=data[-1]['median_price']earliest=data[0]['median_price']appreciation=((latest-earliest)/earliest)*100print(f"{area}: {appreciation:.2f}% price appreciation")
# Analyze current inventory levels by market areacurrent_inventory=client.analytics.get_analytics(filter_query="AnalyticsType eq 'Inventory' and AnalyticsDate ge 2024-01-01T00:00:00Z",select=["MarketArea","InventoryCount","MonthsOfSupply","NewListings","PendingSales","ClosedSales"],orderby="MarketArea asc")print("Current Market Inventory:")forrecordincurrent_inventory:print(f"{record['MarketArea']}:")print(f" Active Listings: {record['InventoryCount']}")print(f" Months of Supply: {record['MonthsOfSupply']}")print(f" New Listings: {record['NewListings']}")print(f" Pending Sales: {record['PendingSales']}")
defget_market_time_series(market_area,start_date,end_date):"""Get time series data for market analysis."""time_series=client.analytics.get_analytics(filter_query=f"MarketArea eq '{market_area}' and AnalyticsDate ge {start_date.isoformat()}Z and AnalyticsDate le {end_date.isoformat()}Z",select=["AnalyticsDate","MedianPrice","AveragePrice","InventoryCount","SalesCount","DaysOnMarket","MonthsOfSupply"],orderby="AnalyticsDate asc")returntime_series# Usagefromdatetimeimportdatetime,timedeltastart=datetime.now()-timedelta(days=365)end=datetime.now()slc_data=get_market_time_series("Salt Lake County",start,end)# Calculate moving averagesdefcalculate_moving_average(data,field,window=3):"""Calculate moving average for a field."""result=[]foriinrange(len(data)):ifi>=window-1:values=[data[j][field]forjinrange(i-window+1,i+1)]avg=sum(values)/len(values)result.append(avg)else:result.append(None)returnresultprice_ma=calculate_moving_average(slc_data,'MedianPrice',3)
defcompare_markets(market_areas,metric='MedianPrice'):"""Compare multiple market areas on a specific metric."""comparison_data={}forareainmarket_areas:area_data=client.analytics.get_analytics(filter_query=f"MarketArea eq '{area}' and AnalyticsDate ge 2024-01-01T00:00:00Z",select=["AnalyticsDate",metric],orderby="AnalyticsDate desc",top=12# Last 12 months)comparison_data[area]=area_datareturncomparison_data# Usagemarkets=["Salt Lake County","Utah County","Davis County"]price_comparison=compare_markets(markets,'MedianPrice')formarket,datainprice_comparison.items():ifdata:latest_price=data[0]['MedianPrice']print(f"{market}: ${latest_price:,}")
defexport_analytics_to_csv(market_areas,start_date,end_date,filename):"""Export analytics data to CSV file."""importcsvfromdatetimeimportdatetimeall_data=[]forareainmarket_areas:area_data=client.analytics.get_analytics(filter_query=f"MarketArea eq '{area}' and AnalyticsDate ge {start_date.isoformat()}Z and AnalyticsDate le {end_date.isoformat()}Z",orderby="AnalyticsDate asc")all_data.extend(area_data)ifnotall_data:print("No data found for export")return# Get all unique field namesfieldnames=set()forrecordinall_data:fieldnames.update(record.keys())fieldnames=sorted(list(fieldnames))withopen(filename,'w',newline='',encoding='utf-8')ascsvfile:writer=csv.DictWriter(csvfile,fieldnames=fieldnames)writer.writeheader()writer.writerows(all_data)print(f"Exported {len(all_data)} records to {filename}")# Usagefromdatetimeimportdatetime,timedeltastart=datetime.now()-timedelta(days=90)end=datetime.now()markets=["Salt Lake County","Utah County"]export_analytics_to_csv(markets,start,end,"market_analytics.csv")
fromwfrmls.exceptionsimportWFRMLSError,NotFoundError,ValidationErrortry:# Attempt to get analyticsanalytics=client.analytics.get_analytic("INVALID_KEY")exceptNotFoundError:print("Analytics record not found")exceptValidationErrorase:print(f"Invalid request: {e}")exceptWFRMLSErrorase:print(f"API error: {e}")
# Use specific date ranges and select fields for better performanceanalytics=client.analytics.get_analytics(filter_query="AnalyticsDate ge 2024-01-01T00:00:00Z and MarketArea eq 'Salt Lake County'",select=["AnalyticsDate","MedianPrice","InventoryCount","SalesCount"],orderby="AnalyticsDate desc",top=50)# Cache frequently accessed datafromfunctoolsimportlru_cachefromdatetimeimportdatetime,timedelta@lru_cache(maxsize=100)defget_cached_market_data(market_area,days_back=30):"""Get market data with caching."""start_date=datetime.now()-timedelta(days=days_back)returnclient.analytics.get_analytics(filter_query=f"MarketArea eq '{market_area}' and AnalyticsDate ge {start_date.isoformat()}Z",orderby="AnalyticsDate desc")
defvalidate_analytics_data(data):"""Validate analytics data for completeness and accuracy."""issues=[]forrecordindata:# Check for required fieldsrequired_fields=['AnalyticsDate','MarketArea','MedianPrice']forfieldinrequired_fields:iffieldnotinrecordorrecord[field]isNone:issues.append(f"Missing {field} in record {record.get('AnalyticsKey','unknown')}")# Check for reasonable valuesif'MedianPrice'inrecordandrecord['MedianPrice']<0:issues.append(f"Negative median price in record {record.get('AnalyticsKey')}")if'InventoryCount'inrecordandrecord['InventoryCount']<0:issues.append(f"Negative inventory count in record {record.get('AnalyticsKey')}")returnissues# Usagedata=client.analytics.get_analytics(top=100)validation_issues=validate_analytics_data(data)ifvalidation_issues:print("Data validation issues found:")forissueinvalidation_issues:print(f" - {issue}")