Synaplan
Open-source AI platform for companies: self-hosted AI agents, GDPR-compliant chatbot widget, RAG knowledge base, WhatsApp and Outlook AI, MCP, multi-model routing. Docker, Kubernetes or hosted in Germ
翻訳待ち
Loading the full README. The saved excerpt is shown below.
Turn forecasts into inventory decisions you can simulate, inspect, and evaluate.
A forecast is not a decision. Its real value depends on the downstream choices
it improves, and ultimately on the operational performance those choices
deliver.Read the full README ↗A forecast is not a decision. Its real value depends on the downstream choices it improves, and ultimately on the operational performance those choices deliver.
Stockcast brings this idea to inventory management: it is the layer between the forecast and the replenishment decision. It maps forecasts from any model into orders, simulates their execution against historical or simulated demand, and evaluates the resulting impact against business metrics such as cost, service, and waste. Happy with a policy? Put it into production with the same objects.
Inspired by PyTorch-style libraries, it is built from Lego-like pieces that snap onto one engine. Each piece is a class you can subclass and adjust.
Stockcast is developed and maintained by Filotas Theodosiou at the Predictive AI and Digital Shift (PADS) research group, VIVES University of Applied Sciences.
pip install stockcast
Stockcast needs Python 3.10+ and only NumPy, pandas, and Matplotlib.
A tea shop sells about six packs a day and orders every morning. Turn its forecast into orders and play out eight weeks:
import numpy as np
import pandas as pd
from stockcast.core import InventoryStateDataFrame, SimulationEngine
from stockcast.evaluation import InventoryEvaluator, avg_on_hand, fill_rate
from stockcast.policies import OrderUpToPolicy
# Eight weeks of daily tea sales.
days = pd.date_range("2026-02-02", periods=56, freq="D")
demand = pd.DataFrame({
"unique_id": "tea",
"date": days,
"y": np.random.default_rng(3).poisson(6, len(days)),
})
# The forecast, from any model: a day's demand is 10 packs or fewer, with
# 95% probability.
forecast = pd.DataFrame({
"unique_id": ["tea"],
"date": [days[0]], # the day it forecasts
"q95": [10], # the 95% quantile
})
# The shelf today.
shelf = InventoryStateDataFrame.from_observed(pd.DataFrame({
"unique_id": ["tea"],
"date": [pd.Timestamp("2026-02-01")],
"on_hand": [30],
}))
policy = OrderUpToPolicy(
lead_time=0, # delivered before the shop opens
review_period=1, # order every morning
freq="D", # one period is one day
service_level=0.95, # the probability the forecast quantile stands for
allow_backorders=False, # a missed sale is lost
)
policy.fit(forecast, target_column="q95")
result = SimulationEngine().run(policy=policy, demand_source=demand, inventory=shelf)
InventoryEvaluator().fit(result).evaluate([fill_rate, avg_on_hand]).round(2)
fill_rate avg_on_hand
0 0.99 4.75
result.to_event_frame() holds the full record: one checked row per SKU and
day, with every receipt, order, sale, and shortage. The
Quickstart
builds the forecast from past sales, and
Walkthrough step 3
shows orders that must cover a lead time.
Stockcast is built on seven principles. Our Philosophy explains each one, with the research behind it.
H = L + R mean the
same thing in every experiment.Research: backtest and compare. For researchers and analysts who measure forecasts by the decisions they lead to. Compare policies, forecasting models, lead times, suppliers, and shelf-life rules on identical demand. Compare scenarios.
Production: run the chosen policy every period. For engineers who put the chosen policy behind a periodic job: load stock, refresh the forecast, compute orders with the supplier's rules, and save the state. From backtest to production.
Stockcast does not forecast, and it does not search for the best policy for you. It gives you the building blocks to do both: any forecasting model can feed it, and any optimiser can wrap it. Version 0.1 models one stocking point with any number of SKUs and suppliers, in discrete periods.
This is the beginning of the README. Read the rest at the original. Read the full README ↗