### Setup Development Environment Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/CONTRIBUTING.md Clone the repository, create and activate a virtual environment, and install the project with optional extras. ```bash git clone https://github.com/ayushtripathi955/main-street-marketplace-toolkit.git cd main-street-marketplace-toolkit python3 -m venv .venv source .venv/bin/activate pip install -e ".[forecasting,notebooks,app,test]" ``` -------------------------------- ### Install Toolkit from Source Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/README.md Install the toolkit by cloning the repository and using pip. This is the recommended method before a PyPI release. ```bash git clone https://github.com/ayushtripathi955/main-street-marketplace-toolkit.git cd main-street-marketplace-toolkit pip install -e . ``` -------------------------------- ### Install Optional Dependencies Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/README.md Install optional dependencies for specific features like forecasting, notebooks, the interactive app, or testing. ```bash pip install -e ".[forecasting]" ``` ```bash pip install -e ".[notebooks]" ``` ```bash pip install -e ".[app]" ``` ```bash pip install -e ".[test]" ``` -------------------------------- ### Install and Run Streamlit App Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/README.md Install the toolkit with app and forecasting dependencies and run the interactive Streamlit application locally. The app does not read or write files or call external APIs. ```bash pip install -e ".[app,forecasting]" streamlit run app/streamlit_app.py ``` -------------------------------- ### Setup and Data Generation Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/03_forecasting_guardrails_walkthrough.ipynb Imports necessary libraries and generates synthetic seller data. It also checks for Prophet availability, which is an optional forecasting library. ```python import warnings warnings.filterwarnings('ignore') import numpy as np import pandas as pd import matplotlib.pyplot as plt from msmt.data import generate_seller_data, PATTERNS from msmt.forecasting import ( auto_select_method, run_forecast, run_guardrails, is_prophet_available, naive_forecast, seasonal_naive_forecast, moving_average_forecast, ses_forecast, holts_forecast, holt_winters_forecast, croston_forecast, prophet_forecast, ) print(f'Prophet available: {is_prophet_available()}') seller_df = generate_seller_data(n_skus=50, n_days=365, seed=42) print(f"Catalog: {len(seller_df):,} rows, " f"{seller_df['sku_id'].nunique()} SKUs, " f"{seller_df['date'].min().date()} → " f"{seller_df['date'].max().date()}") ``` -------------------------------- ### Import Libraries and Generate Synthetic Data Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/04_end_to_end_case_study.ipynb Imports necessary libraries and generates synthetic seller data for a reproducible analysis. This setup is a one-line change away from using real seller portal exports. ```python import warnings; warnings.filterwarnings('ignore') import numpy as np import pandas as pd import matplotlib.pyplot as plt from msmt.data import generate_seller_data from msmt.integrity import ( compute_scorecard, scorecard_for_synthetic_seller, concentration_audit, ) from msmt.resilience import stockout_heatmap_data from msmt.forecasting import run_forecast, run_guardrails SEED = 42 catalog = generate_seller_data(n_skus=50, n_days=365, seed=SEED) print(f"Catalog: {len(catalog):,} rows, " f"{catalog['sku_id'].nunique()} SKUs across " f"{catalog['category'].nunique()} categories") ``` -------------------------------- ### Plotly Import Warning Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/04_end_to_end_case_study.ipynb Indicates that Plotly failed to import, which means interactive plots will not be available. This is a common issue if the library is not installed. ```python Importing plotly failed. Interactive plots will not work. ``` -------------------------------- ### Calculate Safety Stock for Different Demand Patterns Source: https://context7.com/ayushtripathi955/main-street-marketplace-toolkit/llms.txt Demonstrates how to calculate safety stock for normal, KDE (Kernel Density Estimation), and intermittent demand patterns. Ensure necessary libraries like numpy are imported. ```python ss_normal = safety_stock_normal( demand_mean=12.0, demand_std=3.5, lead_time_mean=14.0, lead_time_std=2.0, service_level=0.95, ) print(f"Normal SS: {ss_normal:.1f} units") # Normal SS: 24.3 units ``` ```python history = np.array([8, 7, 12, 9, 11, 85, 94, 90, 70, 12, 9, 8, 7, 10] * 5, dtype=float) samples = [history[i:i+14].sum() for i in range(len(history) - 14)] ss_kde = safety_stock_kde(samples, service_level=0.95) print(f"KDE SS: {ss_kde:.1f} units") # KDE SS: 321.4 units (captures spikes) ``` ```python lumpy_history = [0, 0, 5, 0, 0, 0, 3, 0, 0, 4, 0, 0, 0, 0, 6] * 10 ss_intermittent = safety_stock_intermittent( demand_series=lumpy_history, lead_time_mean=21.0, service_level=0.95 ) print(f"Intermittent SS: {ss_intermittent:.1f} units") ``` -------------------------------- ### Run Local App Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/CONTRIBUTING.md Launch the Streamlit application locally to test its functionality. ```bash .venv/bin/streamlit run app/streamlit_app.py ``` -------------------------------- ### Apply Six Baseline Forecasting Methods Source: https://context7.com/ayushtripathi955/main-street-marketplace-toolkit/llms.txt Demonstrates how to apply six different baseline forecasting methods to a time series. Optionally returns prediction intervals. Ensure the `msmt.forecasting.baselines` module is imported. ```python import numpy as np from msmt.forecasting.baselines import ( naive_forecast, seasonal_naive_forecast, moving_average_forecast, ses_forecast, holts_forecast, holt_winters_forecast, ) series = np.array([10, 12, 9, 14, 11, 13, 10, 12, 11, 14, 10, 13, 9, 15, 11, 13, 12, 14, 10, 13] * 5, dtype=float) horizon = 7 fc_naive = naive_forecast(series, horizon) fc_snaive = seasonal_naive_forecast(series, horizon, season_length=7) fc_ma = moving_average_forecast(series, horizon, window=14) fc_ses, lo_ses, hi_ses = ses_forecast(series, horizon, return_pi=True) fc_holt, lo_h, hi_h = holts_forecast(series, horizon, return_pi=True) fc_hw, lo_hw, hi_hw = holt_winters_forecast(series, horizon, season_length=7, return_pi=True) print("Method | Avg forecast | PI half-width") print(f"Naive | {fc_naive.mean():.2f} | —") print(f"Seasonal Naive | {fc_snaive.mean():.2f} | —") print(f"Moving Average | {fc_ma.mean():.2f} | —") print(f"SES | {fc_ses.mean():.2f} | ±{(hi_ses - fc_ses).mean():.2f}") print(f"Holt's | {fc_holt.mean():.2f} | ±{(hi_h - fc_holt).mean():.2f}") print(f"Holt-Winters | {fc_hw.mean():.2f} | ±{(hi_hw - fc_hw).mean():.2f}") ``` -------------------------------- ### Simulate Regime Change Data Preparation Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/03_forecasting_guardrails_walkthrough.ipynb Prepares historical sales data to simulate a demand surge. It splits the data into pre-spike and post-spike periods, modifying the latter to introduce a 4x increase in units sold over the last 7 days. This is used to test the forecaster's ability to handle sudden changes. ```python smooth_sku = seller_df[seller_df['pattern'] == 'smooth']['sku_id'].iloc[0] smooth_df = seller_df[seller_df['sku_id'] == smooth_sku].sort_values('date').reset_index(drop=True) # Pre-spike: trim off the last 7 days so the forecaster sees only the # original smooth history. pre_spike = smooth_df.iloc[:-7].copy() fc_pre = run_forecast(pre_spike, horizon=28) # Post-spike: replace the last 7 actuals with a 4x surge. post_spike = smooth_df.copy() spike_idx = post_spike.index[-7:] post_spike.loc[spike_idx, 'units_sold'] = ( post_spike.loc[spike_idx, 'units_sold'].values * 4 ).astype(int) print(f'SKU: {smooth_sku}') print(f'Pre-spike trailing-7 mean: {smooth_df.iloc[-14:-7]["units_sold"].mean():.2f}') print(f'Post-spike trailing-7 mean: {post_spike.iloc[-7:]["units_sold"].mean():.2f}') ``` -------------------------------- ### Run Streamlit App Source: https://context7.com/ayushtripathi955/main-street-marketplace-toolkit/llms.txt Execute the Streamlit application to access an interactive UI for the toolkit's features. Ensure you are in the correct directory. ```bash streamlit run app/streamlit_app.py ``` -------------------------------- ### Visualize Stockout-Risk Distribution Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/04_end_to_end_case_study.ipynb Visualizes the distribution of stockout risk levels across the catalog using a bar chart. Requires matplotlib and pandas. ```python fig, ax = plt.subplots(figsize=(9, 3.5)) level_color = {'critical': '#c0392b', 'high': '#e67e22', 'medium': '#f1c40f', 'low': '#27ae60'} counts = heatmap['risk_level'].value_counts().reindex( ['critical', 'high', 'medium', 'low'] ).fillna(0).astype(int) ax.bar(counts.index, counts.values, color=[level_color[l] for l in counts.index]) for i, v in enumerate(counts.values): ax.text(i, v + 0.3, str(int(v)), ha='center', fontsize=10) ax.set_ylabel('Number of SKUs') ax.set_title('Stockout-risk distribution across the catalog', loc='left') ax.spines['top'].set_visible(False); ax.spines['right'].set_visible(False) plt.tight_layout(); plt.show() ``` -------------------------------- ### Forecast and Evaluate At-Risk SKUs Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/04_end_to_end_case_study.ipynb Iterates through the top three at-risk SKUs, generates a forecast for each, calculates a proposed order quantity, and runs guardrails to assess forecast reliability. Prints a summary of the forecast pattern, method, and guardrail status for each SKU. ```python top_at_risk = heatmap.head(3)['sku_id'].tolist() forecasts = [] reports = [] for sku_id in top_at_risk: sub = catalog[catalog['sku_id'] == sku_id] fc = run_forecast(sub, horizon=28) proposed = float(sub['units_sold'].tail(30).mean()) * 30 # ~30 days of stock rep = run_guardrails(sub, fc, proposed_order_qty=proposed) forecasts.append(fc) reports.append(rep) print(f"{sku_id} pattern={fc['pattern']:18s} method={fc['method_used']:16s} " f ``` -------------------------------- ### Visualize Regime Change and Backtest Band Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/03_forecasting_guardrails_walkthrough.ipynb Generates a plot to visualize a regime change in sales data. It displays pre-spike actuals, spiked actuals, the trailing backtest band, and the trailing mean forecast. This helps in understanding how the guardrails' backtest band compares against actual sales during a demand surge. ```python from msmt.forecasting.guardrails import _backtest_band series_post = post_spike['units_sold'].astype(float).to_numpy() dates_post = pd.DatetimeIndex(post_spike['date']) actuals_bt, fc_bt, lo_bt, hi_bt = _backtest_band(series_post, window_days=28, lookback=28) bt_dates = dates_post[-len(actuals_bt):] fig, ax = plt.subplots(figsize=(11, 4.2)) history_window = 90 ax.plot(dates_post[-history_window:-7], series_post[-history_window:-7], color='#34495e', linewidth=1.0, label='pre-spike actuals') ax.plot(dates_post[-7:], series_post[-7:], color='#c0392b', linewidth=2.0, marker='o', markersize=4, label='spiked actuals (last 7d)') ax.fill_between(bt_dates, lo_bt, hi_bt, color='#bdc3c7', alpha=0.30, label='trailing backtest band') ax.plot(bt_dates, fc_bt, color='#7f8c8d', linewidth=1.0, linestyle='--', label='trailing mean') ax.set_title(f"Regime change on {smooth_sku} — last 7 days", loc='left') ax.set_ylabel('units / day') ax.set_xlabel('date') ax.legend(frameon=False, loc='upper left', fontsize=9) ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) plt.tight_layout() plt.show() ``` -------------------------------- ### Generate Stockout Risk Heatmap Data Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/04_end_to_end_case_study.ipynb Generates a heatmap of stockout risk data for a given catalog and service level. Displays the top 10 most at-risk SKUs. ```python heatmap = stockout_heatmap_data(catalog, service_level=0.95) show_cols = [ 'sku_id', 'pattern', 'method_used', 'rop', 'safety_stock', 'current_stock', 'risk_score', 'risk_level', 'days_until_stockout', ] print('Top 10 most at-risk SKUs:') heatmap[show_cols].head(10).round(2) ``` -------------------------------- ### safety_stock_normal / safety_stock_kde / safety_stock_intermittent Source: https://context7.com/ayushtripathi955/main-street-marketplace-toolkit/llms.txt Three safety-stock methods suited to different demand shapes. The normal formula uses combined-variance; KDE uses bootstrapped lead-time-demand percentiles; the intermittent method uses a Croston-inspired CV decomposition. ```APIDOC ## safety_stock_normal / safety_stock_kde / safety_stock_intermittent ### Description Three safety-stock methods suited to different demand shapes. The normal formula uses combined-variance; KDE uses bootstrapped lead-time-demand percentiles; the intermittent method uses a Croston-inspired CV decomposition. ### Method ```python from msmt.resilience.safety_stock import ( safety_stock_normal, safety_stock_kde, safety_stock_intermittent, ) import numpy as np # Example usage for safety_stock_normal (assuming you have demand_mean, demand_cv, lead_time_mean, lead_time_cv, service_level) # safety_stock = safety_stock_normal(demand_mean=10, demand_cv=0.5, lead_time_mean=5, lead_time_cv=0.3, service_level=0.95) # Example usage for safety_stock_kde (assuming you have lead_time_demand_samples) # safety_stock = safety_stock_kde(lead_time_demand_samples=np.random.rand(100)*20, service_level=0.95) # Example usage for safety_stock_intermittent (assuming you have demand_mean, demand_cv, lead_time_mean, service_level) # safety_stock = safety_stock_intermittent(demand_mean=5, demand_cv=2.0, lead_time_mean=10, service_level=0.90) ``` ``` -------------------------------- ### Analyze stockout cost sensitivity to suppression multiplier Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/02_supply_resilience_walkthrough.ipynb Demonstrates how the total stockout cost changes based on different suppression multipliers. This helps in understanding the financial impact of marketplace demotion. Requires 'suppression_adjusted_stockout_cost' and 'pandas' (as 'pd'). ```python # Sensitivity: how does total cost change with the suppression # multiplier the seller believes in? rows = [] for mult in [1.0, 1.5, 2.0, 2.5, 3.0, 4.0]: s = suppression_adjusted_stockout_cost( daily_profit=120.0, stockout_days=7, suppression_multiplier=mult, ) rows.append({ 'multiplier': mult, 'direct_cost': s['direct_cost'], 'suppression_cost': s['suppression_cost'], 'total_cost': s['total_cost'], }) pd.DataFrame(rows).round(2) ``` -------------------------------- ### Generate Synthetic Seller Scorecard Source: https://context7.com/ayushtripathi955/main-street-marketplace-toolkit/llms.txt Generates a synthetic seller and runs the scorecard in one call. Useful for demos and notebooks without real seller input. ```python from msmt.integrity.scorecard import scorecard_for_synthetic_seller result = scorecard_for_synthetic_seller(seed=42) print(result["overall_score"]) # e.g. 74.3 print(result["suppression_risk"]) # "medium" print(len(result["top_issues"])) # up to 3 print(result["signal_scores"]["on_time_shipment_rate"]) # {'value': 0.94, 'score_0_to_100': 57.1, 'rating': 'fair', 'weight': 0.15, ...} ``` -------------------------------- ### Run Test Suite Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/CONTRIBUTING.md Execute the project's test suite using pytest. Ensure tests remain stable or grow with new contributions. ```bash .venv/bin/python -m pytest tests/ -q ``` -------------------------------- ### Generate and Summarize Catalog Data Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/01_marketplace_integrity_walkthrough.ipynb Generates synthetic seller catalog data and then aggregates it to calculate the total units sold per category and SKU. Used as input for concentration risk analysis. ```python catalog = generate_seller_data(n_skus=50, n_days=365, seed=42) agg = catalog.groupby(['category', 'sku_id'])['units_sold'].sum().reset_index() print(f'categories: {agg["category"].nunique()} ' f'SKUs: {agg["sku_id"].nunique()} ' f'rows: {len(agg)}') agg.head() ``` -------------------------------- ### Safety Stock Calculations Source: https://context7.com/ayushtripathi955/main-street-marketplace-toolkit/llms.txt Provides three safety-stock calculation methods: normal (combined-variance), KDE (bootstrapped percentiles), and intermittent (Croston-inspired CV decomposition). ```python from msmt.resilience.safety_stock import ( safety_stock_normal, safety_stock_kde, safety_stock_intermittent, ) import numpy as np ``` -------------------------------- ### Run Auto-Selecting Single-SKU Demand Forecast Source: https://context7.com/ayushtripathi955/main-street-marketplace-toolkit/llms.txt Automatically selects the best forecasting method for a single SKU based on its historical data and provides a forecast with a 95% prediction interval. Requires historical SKU data. ```python from msmt.data import generate_weekly_seasonal from msmt.forecasting.auto_select import run_forecast sku_df = generate_weekly_seasonal(n_days=365, seed=3) result = run_forecast(sku_df, horizon=28) print(result["pattern"]) print(result["method_used"]) print(result["forecast"][:7]) print(result["lower_95"][:7]) print(result["upper_95"][:7]) print(result["horizon_dates"]) ``` -------------------------------- ### Visualize SKU Forecasts Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/04_end_to_end_case_study.ipynb Generates plots for each SKU's forecast, showing historical actuals, the forecast line, and the 95% prediction interval. This helps visualize the forecast accuracy and confidence. ```python fig, axes = plt.subplots(len(forecasts), 1, figsize=(10, 3.0 * len(forecasts))) if len(forecasts) == 1: axes = [axes] for ax, fc in zip(axes, forecasts): sub = catalog[catalog['sku_id'] == fc['sku_id']].sort_values('date') history = sub.tail(90) ax.plot(history['date'], history['units_sold'], color='#34495e', linewidth=1.0, label='actuals (last 90d)') ax.plot(fc['horizon_dates'], fc['forecast'], color='#2980b9', linewidth=2.0, label=f"forecast ({fc['method_used']})") ax.fill_between(fc['horizon_dates'], fc['lower_95'], fc['upper_95'], color='#3498db', alpha=0.18, label='95% PI') ax.set_title(f"{fc['sku_id']} ({fc['pattern']})", loc='left', fontsize=11) ax.set_ylabel('units / day') ax.legend(frameon=False, loc='upper left', fontsize=8) ax.spines['top'].set_visible(False); ax.spines['right'].set_visible(False) axes[-1].set_xlabel('date') plt.tight_layout(); plt.show() ``` -------------------------------- ### Execute Individual Guardrail Functions Source: https://context7.com/ayushtripathi955/main-street-marketplace-toolkit/llms.txt Shows how to call each of the five guardrail functions independently. This is useful when managing the data pipeline manually. Each function returns a dictionary with status and relevant metrics. ```python from msmt.forecasting.guardrails import ( drift_detection, confidence_floor, regime_change_detection, reorder_cap, graceful_degradation, ) import numpy as np actuals = np.array([10, 12, 9, 11, 13, 14, 12, 11, 10, 12, 11, 14, 13, 12]) forecasts = np.array([12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12]) # 1. Drift: is the model consistently over- or under-forecasting? d = drift_detection(actuals, forecasts, threshold_weeks=2) print(d["fired"], d["direction"]) # False, None # 2. Confidence floor: is the PI too wide to plan against? forecast = np.full(7, 12.0) c = confidence_floor(forecast, forecast - 8, forecast + 8, threshold_ratio=0.50) print(c["fired"], f"PI ratio: {c['pi_ratio']:.2f}") # True PI ratio: 1.33 # 3. Regime change: have actuals left the band repeatedly? lo = np.full(len(actuals), 8.0) hi = np.full(len(actuals), 14.0) r = regime_change_detection(actuals, lo, hi, window_days=7, threshold_days=5) print(r["fired"], r["outside_count"]) # False 0 # 4. Reorder cap: is the proposed order unreasonably large? cap = reorder_cap(proposed_order_qty=450, trailing_30d_avg=12.0, cap_multiplier=3.0) print(cap["fired"], cap["cap_qty"]) # True 36.0 # 5. Graceful degradation: what fallback to use when primary fails? deg = graceful_degradation("smooth", actuals, horizon=14, primary_forecast_failed=True) print(deg["method_name"], deg["forecast"][:3]) # trailing_30d_mean [11.6 11.6 11.6] ``` -------------------------------- ### Visualize SKU stockout risk levels Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/02_supply_resilience_walkthrough.ipynb Generates a bar chart showing the count of SKUs for each risk level (critical, high, medium, low). Uses predefined colors for each risk level. Ensure 'heatmap' DataFrame and 'plt' are available. ```python plt.style.use('default') level_order = ['critical', 'high', 'medium', 'low'] level_colors = { 'critical': '#c0392b', 'high': '#e67e22', 'medium': '#f1c40f', 'low': '#27ae60', } counts = heatmap['risk_level'].value_counts().reindex(level_order).fillna(0).astype(int) fig, ax = plt.subplots(figsize=(7, 4)) ax.bar(counts.index, counts.values, color=[level_colors[l] for l in counts.index]) ax.set_title('SKUs by stockout-risk level') ax.set_xlabel('Risk level') ax.set_ylabel('Number of SKUs') for i, v in enumerate(counts.values): ax.text(i, v + 0.3, str(v), ha='center', fontsize=11) ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) plt.tight_layout() plt.show() ``` -------------------------------- ### Generate Synthetic Multi-SKU Dataset Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/README.md Generate a synthetic dataset with multiple SKUs and daily sales data. The output DataFrame follows a specific schema expected by the toolkit. ```python from msmt.data import generate_seller_data df = generate_seller_data(n_skus=50, n_days=365, seed=42) print(df.head()) print(df["pattern"].value_counts()) ``` -------------------------------- ### Run Catalog-Wide Demand Forecasts Source: https://context7.com/ayushtripathi955/main-street-marketplace-toolkit/llms.txt Applies the `run_forecast` function to every SKU in a multi-SKU DataFrame. Returns a list of forecast dictionaries, one for each SKU. Requires a DataFrame containing data for multiple SKUs. ```python from msmt.data import generate_seller_data from msmt.forecasting.auto_select import batch_forecast df = generate_seller_data(n_skus=10, n_days=365, seed=1) forecasts = batch_forecast(df, horizon=14) for fc in forecasts: avg = fc["forecast"].mean() print(f"{fc['sku_id']:15s} | {fc['pattern']:18s} | {fc['method_used']:15s} | avg {avg:.1f} u/day") ``` -------------------------------- ### Run Guardrails with Proposed Order Quantity Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/03_forecasting_guardrails_walkthrough.ipynb Applies all five forecasting guardrails to a post-spike sales history and a deliberately oversized proposed order quantity. This tests the guardrails' ability to detect regime changes and reorder caps, providing an overall recommendation for manual review. ```python trailing_30 = post_spike['units_sold'].tail(30).mean() proposed_qty = trailing_30 * 6 # 6x — should fire the cap report = run_guardrails(post_spike, fc_pre, proposed_order_qty=proposed_qty) print(f"SKU: {report['sku_id']}") print(f"Any guardrail fired: {report['any_fired']}") print(f"Overall: {report['overall_recommendation']}") print() for name, g in report['guardrails'].items(): fired = g.get('fired') flag = 'FIRED' if fired else ' ok ' print(f" [{flag}] {name:13s} {g.get('recommendation', '')}") ``` -------------------------------- ### Display Top Issues and Recommendations Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/01_marketplace_integrity_walkthrough.ipynb Iterates through the top issues and their corresponding plain-English recommendations from a scorecard. Useful for presenting actionable insights to sellers. ```python for issue, rec in zip(scorecard['top_issues'], scorecard['recommendations']): print(f"\u2022 {issue['plain_english']}") print(f" → {rec}") print() ``` -------------------------------- ### reorder_point_for_sku Source: https://context7.com/ayushtripathi955/main-street-marketplace-toolkit/llms.txt Classifies demand, selects the appropriate safety-stock method (normal for smooth/seasonal, KDE for holiday spikes, Croston-inspired for intermittent), and computes both safety stock and reorder point in one call. ```APIDOC ## reorder_point_for_sku ### Description Classifies demand, selects the appropriate safety-stock method (normal for smooth/seasonal, KDE for holiday spikes, Croston-inspired for intermittent), and computes both safety stock and reorder point in one call. ### Method ```python from msmt.data import generate_weekly_seasonal from msmt.resilience.reorder_point import reorder_point_for_sku sku_df = generate_weekly_seasonal(n_days=180, seed=5) result = reorder_point_for_sku(sku_df, service_level=0.95) print(result) # Override the pattern if you already know it result_override = reorder_point_for_sku(sku_df, service_level=0.99, pattern="smooth") print(f"ROP at 99% SL: {result_override['rop']:.1f}") ``` ### Response Example ```json { "rop": 47.3, "safety_stock": 18.9, "method_used": "normal", "pattern": "weekly_seasonal", "demand_mean": 12.8, "lead_time_mean": 22.0 } ``` ``` -------------------------------- ### Calculate Stockout Risk Heatmap Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/02_supply_resilience_walkthrough.ipynb Generates a stockout risk heatmap by chaining classification, safety stock, reorder point, and risk score calculations. Use this to rank SKUs by their stockout risk. ```python from msmt.resilience import stockout_heatmap_data heatmap = stockout_heatmap_data(seller_df, service_level=service_level) print(f"SKUs analyzed: {len(heatmap)}") heatmap.head(10).round(2) ``` -------------------------------- ### Synthetic Data Generation Output Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/04_end_to_end_case_study.ipynb Displays the dimensions of the generated synthetic catalog, including the number of rows, unique SKUs, and categories. This confirms the data generation step was successful. ```python Catalog: 18,250 rows, 50 SKUs across 8 categories ``` -------------------------------- ### Generate Catalog-Level Stockout Risk Heatmap Data Source: https://context7.com/ayushtripathi955/main-street-marketplace-toolkit/llms.txt This function processes an entire SKU catalog to identify stockout risks. It requires seller data generated by `generate_seller_data` and returns a DataFrame suitable for analysis and visualization. ```python from msmt.data import generate_seller_data from msmt.resilience.stockout_risk import stockout_heatmap_data df = generate_seller_data(n_skus=20, n_days=365, seed=99) heatmap = stockout_heatmap_data(df, service_level=0.95) print(heatmap[["sku_id", "pattern", "risk_level", "days_until_stockout", "action"]].head(5)) ``` ```python # Filter to critical + high risk SKUs only at_risk = heatmap[heatmap["risk_level"].isin(["critical", "high"])] print(f"{len(at_risk)} SKUs require immediate or near-term reorder action.") ``` -------------------------------- ### Select Representative SKUs by Pattern Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/03_forecasting_guardrails_walkthrough.ipynb Identifies a single SKU for each demand pattern to ensure all patterns are represented in subsequent analyses. This is useful for testing and demonstration purposes. ```python representatives = {} for p in PATTERNS: sku_ids = seller_df[seller_df['pattern'] == p]['sku_id'].unique() if len(sku_ids): representatives[p] = sku_ids[0] representatives ``` -------------------------------- ### batch_forecast Source: https://context7.com/ayushtripathi955/main-street-marketplace-toolkit/llms.txt Performs demand forecasting for an entire catalog of SKUs by applying `run_forecast` to each SKU. ```APIDOC ## batch_forecast ### Description Runs `run_forecast` for every SKU in a multi-SKU DataFrame and returns a list of forecast dicts in SKU order. ### Method `batch_forecast(df, horizon)` ### Parameters #### Path Parameters None #### Query Parameters * **df** (DataFrame) - Required - DataFrame containing historical demand data for multiple SKUs. * **horizon** (int) - Required - The number of future periods to forecast for each SKU. ### Request Example ```python from msmt.data import generate_seller_data from msmt.forecasting.auto_select import batch_forecast df = generate_seller_data(n_skus=10, n_days=365, seed=1) forecasts = batch_forecast(df, horizon=14) for fc in forecasts: avg = fc["forecast"].mean() print(f"{fc['sku_id']:15s} | {fc['pattern']:18s} | {fc['method_used']:15s} | avg {avg:.1f} u/day") ``` ### Response #### Success Response (list of dicts) Returns a list where each element is a dictionary containing the forecast results for a single SKU, as produced by `run_forecast`. #### Response Example ``` # SKU-SM-0001 | smooth | ses | avg 11.9 u/day # SKU-WS-0002 | weekly_seasonal | holt_winters | avg 13.4 u/day # SKU-IM-0003 | intermittent | croston | avg 1.8 u/day ``` ``` -------------------------------- ### Chart Actuals + Forecast + PI Band per Pattern Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/03_forecasting_guardrails_walkthrough.ipynb Visualizes the historical data, forecast, and 95% prediction interval (PI) for each representative SKU and pattern. The width of the PI band indicates the model's confidence in the forecast. Use this to assess forecast precision and plan safety stock. ```python plt.style.use('default') fig, axes = plt.subplots(len(results), 1, figsize=(11, 3.0 * len(results)), sharex=False) if len(results) == 1: axes = [axes] for ax, (pattern, r) in zip(axes, results.items()): history_window = 90 h_dates = r['dates'][-history_window:] h_series = r['series'][-history_window:] f_dates = r['horizon_dates'] ax.plot(h_dates, h_series, color='#34495e', linewidth=1.0, label='actuals (last 90d)') ax.plot(f_dates, r['forecast'], color='#2980b9', linewidth=2.0, label=f"forecast ({r['method_used']})") ax.fill_between(f_dates, r['lower_95'], r['upper_95'], color='#3498db', alpha=0.18, label='95% PI') ax.axvline(h_dates[-1], color='#bdc3c7', linestyle='--', linewidth=0.8) ax.set_title(f'{pattern} → {r["method_used"]}', loc='left', fontsize=11) ax.set_ylabel('units / day') ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) ax.legend(frameon=False, loc='upper left', fontsize=8) axes[-1].set_xlabel('date') plt.tight_layout() plt.show() ``` -------------------------------- ### Compute Safety Stock and Reorder Points Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/02_supply_resilience_walkthrough.ipynb Iterates through each SKU's demand data, computes the reorder point, safety stock, and method used via `reorder_point_for_sku`, and stores the results in a DataFrame. This is useful for a 95% service level. ```python from msmt.resilience import reorder_point_for_sku service_level = 0.95 rop_rows = [] for sku_id, sub in seller_df.groupby('sku_id', sort=False): info = reorder_point_for_sku(sub, service_level=service_level) rop_rows.append({'sku_id': sku_id, **info}) rop_df = pd.DataFrame(rop_rows).round(2) rop_df.head(10) ``` -------------------------------- ### scorecard_for_synthetic_seller Source: https://context7.com/ayushtripathi955/main-street-marketplace-toolkit/llms.txt Generates a plausible synthetic seller and runs the scorecard in one call. Useful for demos, notebooks, and Streamlit app pages that don't need real seller input. ```APIDOC ## scorecard_for_synthetic_seller ### Description Generates a plausible synthetic seller and runs the scorecard in one call. Useful for demos, notebooks, and Streamlit app pages that don't need real seller input. ### Method ```python from msmt.integrity.scorecard import scorecard_for_synthetic_seller result = scorecard_for_synthetic_seller(seed=42) print(result["overall_score"]) print(result["suppression_risk"]) print(len(result["top_issues"])) print(result["signal_scores"]["on_time_shipment_rate"]) ``` ### Response Example ```json { "overall_score": 74.3, "suppression_risk": "medium", "top_issues": [ "Your on-time shipment rate is below platform thresholds...", "Your return rate is elevated. High returns signal listing-reality mismatch...", "Listing-quality score is below the 'good' threshold..." ], "signal_scores": { "on_time_shipment_rate": { "value": 0.94, "score_0_to_100": 57.1, "rating": "fair", "weight": 0.15 } } } ``` ``` -------------------------------- ### msmt.data.generate_new_sku Source: https://context7.com/ayushtripathi955/main-street-marketplace-toolkit/llms.txt Generates synthetic data for a single SKU with a post-launch ramp-up period. ```APIDOC ## msmt.data.generate_new_sku ### Description Generates a single SKU's demand data simulating a new product launch, including an initial ramp-up period. This function is part of the per-pattern generators in the `msmt.data` module. ### Parameters - **n_days** (int) - Number of days to generate data for. - **seed** (int) - Seed for reproducibility. - **history_days** (int, optional) - The number of days representing the post-launch ramp-up period. Defaults to 45. - **target_mean_units** (float, optional) - The target average daily units sold after the ramp-up. Defaults to 9.0. - **end_date** (str, optional) - An optional end date anchor for the generated data. ### Request Example ```python from msmt.data import generate_new_sku data = generate_new_sku(n_days=365, seed=0, history_days=45, target_mean_units=9.0) ``` ### Response #### Success Response (DataFrame) - **date** (datetime64[ns]) - The date of the record. - **sku_id** (object) - Unique identifier for the SKU. - **units_sold** (int) - Number of units sold on that day. - **listing_price** (float64) - The price of the listing. - **stock_on_hand** (int) - The number of units in stock. - **lead_time_days** (int) - The lead time in days. - **category** (object) - The category of the product. - **pattern** (object) - The demand pattern archetype (will be 'new_sku'). ``` -------------------------------- ### Visualize Guardrail Status Summary Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/03_forecasting_guardrails_walkthrough.ipynb Generates a horizontal bar chart to visualize which guardrails have fired and displays their plain-English recommendations. This is useful for a quick overview of forecast health. ```python guard_order = ['drift', 'confidence', 'regime', 'cap', 'degradation'] labels = [] fired_flags = [] recs = [] for name in guard_order: g = report['guardrails'][name] labels.append(name) fired_flags.append(bool(g.get('fired'))) recs.append(g.get('recommendation', '')) fig, ax = plt.subplots(figsize=(11, 3.6)) y_pos = np.arange(len(labels)) colors = ['#c0392b' if f else '#27ae60' for f in fired_flags] ax.barh(y_pos, [1] * len(labels), color=colors, alpha=0.9) for i, (name, fired, rec) in enumerate(zip(labels, fired_flags, recs)): label = 'FIRED' if fired else 'ok' ax.text(0.02, i, f'{name} — {label}', va='center', color='white', fontsize=10, fontweight='bold') ax.text(1.02, i, rec[:90] + ('...' if len(rec) > 90 else ''), va='center', fontsize=9, color='#2c3e50') ax.set_yticks([]) ax.set_xticks([]) ax.set_xlim(0, 4.5) for s in ['top', 'right', 'bottom', 'left']: ax.spines[s].set_visible(False) ax.set_title('Guardrail status', loc='left', fontsize=12) plt.tight_layout() plt.show() ``` -------------------------------- ### Generate Synthetic Seller Data Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/02_supply_resilience_walkthrough.ipynb Generates a synthetic dataset for a specified number of SKUs and days. This data simulates daily sales, pricing, and stock levels, including lead times, categories, and demand patterns. Useful for testing supply chain algorithms without real data. ```python import pandas as pd import numpy as np import matplotlib.pyplot as plt from msmt.data import generate_seller_data seller_df = generate_seller_data(n_skus=50, n_days=365, seed=42) print(f"rows: {len(seller_df):,} | unique SKUs: " f"{seller_df['sku_id'].nunique()} | date range: " f"{seller_df['date'].min().date()} → " f"{seller_df['date'].max().date()}") seller_df.head() ``` -------------------------------- ### stockout_heatmap_data Source: https://context7.com/ayushtripathi955/main-street-marketplace-toolkit/llms.txt Generates a catalog-level stockout risk heatmap by running a pipeline across all SKUs. It returns a ranked DataFrame suitable for plotting or triage, indicating risk levels and actions. ```APIDOC ## stockout_heatmap_data ### Description Runs the full classify → safety-stock → ROP → risk pipeline across every SKU in a catalog and returns a ranked DataFrame for plotting or triage. ### Method `stockout_heatmap_data(df, service_level=0.95)` ### Parameters #### Path Parameters None #### Query Parameters * **df** (DataFrame) - Required - DataFrame containing SKU data. * **service_level** (float) - Optional - The desired service level (default: 0.95). ### Request Example ```python from msmt.data import generate_seller_data from msmt.resilience.stockout_risk import stockout_heatmap_data df = generate_seller_data(n_skus=20, n_days=365, seed=99) heatmap = stockout_heatmap_data(df, service_level=0.95) print(heatmap[["sku_id", "pattern", "risk_level", "days_until_stockout", "action"]].head(5)) ``` ### Response #### Success Response (DataFrame) Returns a DataFrame with columns including 'sku_id', 'pattern', 'risk_level', 'days_until_stockout', and 'action'. #### Response Example ``` # sku_id pattern risk_level days_until_stockout action # 0 SKU-IM-0001 intermittent critical 1.2 Place an emergency reorder today... # 1 SKU-NS-0002 new_sku high 4.7 Reorder this week — at the current... # 2 SKU-WS-0003 weekly_seasonal medium 11.3 Schedule a reorder in the next two... ``` ### Additional Usage ```python # Filter to critical + high risk SKUs only at_risk = heatmap[heatmap["risk_level"].isin(["critical", "high"])] print(f"{len(at_risk)} SKUs require immediate or near-term reorder action.") ``` ``` -------------------------------- ### Visualize SKU stock levels vs. reorder points Source: https://github.com/ayushtripathi955/main-street-marketplace-toolkit/blob/main/notebooks/02_supply_resilience_walkthrough.ipynb Creates a scatter plot comparing current stock on hand against the reorder point for each SKU, color-coded by risk level. Includes a dashed line indicating where current stock equals the reorder point. Ensure 'heatmap' DataFrame, 'plt', and 'level_order' are available. ```python fig, ax = plt.subplots(figsize=(8, 5)) for level in level_order: sub = heatmap[heatmap['risk_level'] == level] if sub.empty: continue ax.scatter( sub['rop'], sub['current_stock'], s=70, alpha=0.85, edgecolors='white', linewidth=0.6, color=level_colors[level], label=level, ) lim = max(heatmap['rop'].max(), heatmap['current_stock'].max()) * 1.05 ax.plot([0, lim], [0, lim], color='#7f8c8d', linestyle='--', linewidth=1, label='current stock = ROP') ax.set_xlim(0, lim) ax.set_ylim(0, lim) ax.set_xlabel('Reorder point (units)') ax.set_ylabel('Current stock on hand (units)') ax.set_title('Where each SKU sits relative to its reorder point') ax.legend(title='Risk level', loc='upper left', frameon=False) ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) plt.tight_layout() plt.show() ``` -------------------------------- ### run_forecast Source: https://context7.com/ayushtripathi955/main-street-marketplace-toolkit/llms.txt Performs an auto-selected, single-SKU demand forecast, providing a point forecast and a 95% prediction interval. ```APIDOC ## run_forecast ### Description Auto-selecting single-SKU forecast. Classifies the SKU, picks the recommended method (naive → MA → SES → Holt → Holt-Winters → Croston → Prophet), and returns a point forecast plus 95% prediction interval. ### Method `run_forecast(sku_df, horizon)` ### Parameters #### Path Parameters None #### Query Parameters * **sku_df** (DataFrame) - Required - DataFrame containing historical demand data for a single SKU. * **horizon** (int) - Required - The number of future periods to forecast. ### Request Example ```python from msmt.data import generate_weekly_seasonal from msmt.forecasting.auto_select import run_forecast sku_df = generate_weekly_seasonal(n_days=365, seed=3) result = run_forecast(sku_df, horizon=28) print(result["pattern"]) print(result["method_used"]) print(result["forecast"][:7]) print(result["lower_95"][:7]) print(result["upper_95"][:7]) print(result["horizon_dates"]) ``` ### Response #### Success Response (dict) Returns a dictionary containing: - **pattern** (str): The identified demand pattern (e.g., 'weekly_seasonal'). - **method_used** (str): The forecasting method selected. - **forecast** (numpy.ndarray): The point forecast for the horizon. - **lower_95** (numpy.ndarray): The lower bound of the 95% prediction interval. - **upper_95** (numpy.ndarray): The upper bound of the 95% prediction interval. - **horizon_dates** (DatetimeIndex): The dates corresponding to the forecast horizon. #### Response Example ``` weekly_seasonal holt_winters [13.4, 18.2, 17.9, 14.1, 13.8, 19.5, 20.1] # 95% PI lower bound values # 95% PI upper bound values # DatetimeIndex(['2026-01-01', ...], length=28) ``` ```