-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrun_model.py
More file actions
78 lines (64 loc) · 2.64 KB
/
Copy pathrun_model.py
File metadata and controls
78 lines (64 loc) · 2.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
"""Single-run CLI: run the model and export CSV/JSON artifacts."""
from __future__ import annotations
import argparse
from pathlib import Path
from spatial_market_lockin import ModelConfig, SpatialMarketModel
from spatial_market_lockin.export import export_run
from spatial_market_lockin.metrics import summarize_run
from spatial_market_lockin.scenarios import (
DEFAULT_SCENARIO,
scenario_names,
scenario_overrides,
)
# CLI flags that map directly onto ModelConfig fields. Only those the user
# actually passes are forwarded as overrides, so unset flags keep scenario /
# config defaults rather than clobbering them with None.
_CONFIG_OVERRIDES = ("num_buyers", "num_sellers", "grid_size")
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--seed", type=int, default=None, help="random seed")
parser.add_argument("--steps", type=int, default=500, help="number of ticks to run")
parser.add_argument(
"--scenario",
choices=scenario_names(),
default=DEFAULT_SCENARIO,
help="named parameter scenario applied before explicit flags",
)
parser.add_argument("--num-buyers", type=int, default=None)
parser.add_argument("--num-sellers", type=int, default=None)
parser.add_argument("--grid-size", type=int, default=None)
parser.add_argument(
"--output-dir",
type=Path,
default=None,
help="where to write outputs (default: outputs/run_seed_<seed>_steps_<steps>)",
)
return parser
def main(argv: list[str] | None = None) -> None:
args = build_parser().parse_args(argv)
# Scenario sets the base overrides; explicit flags win over the scenario.
overrides = scenario_overrides(args.scenario)
overrides.update(
{
name: getattr(args, name)
for name in _CONFIG_OVERRIDES
if getattr(args, name) is not None
}
)
config = ModelConfig(seed=args.seed, steps=args.steps, **overrides)
model = SpatialMarketModel(config)
model.run()
output_dir = args.output_dir or (
Path("outputs") / f"run_seed_{args.seed}_steps_{args.steps}"
)
export_run(model, output_dir, extra_metadata={"scenario": args.scenario})
summary = summarize_run(model)
print(f"Run complete [{args.scenario}]: {model.tick} ticks -> {output_dir}")
print(
f" switch_rate={summary['switch_rate']:.3f} | "
f"never_transacted={summary['never_transacted']:.3f} | "
f"avg_transaction_price={summary['avg_transaction_price']:.3f} | "
f"price_cv={summary['price_cv']:.3f}"
)
if __name__ == "__main__":
main()