Run the full three-year dispatch and fix issues it surfaced
CI / test (push) Successful in 14s

Executed battery-dispatch run over the full 2018-2020 Attachment 2
series (225.9s, 1096 rolling-horizon windows) and committed the
results: outputs/ (dispatch.csv, annual/monthly summaries, summary.json,
four figures), README.md (setup, run instructions, assumptions, the
one-paragraph approach summary) and RESULTS.md (headline numbers,
per-year table, charts, commentary).

The full run surfaced three real issues, all fixed rather than papered
over:

- validate_schedule's soc_within_bounds check used a fixed 1e-6 MWh
  tolerance for the "state of charge below zero" case, while its
  sibling soc_matches_power_flows check already scales its tolerance
  with sqrt(n) for the same reason (CBC's own solver precision
  accumulating over a long cumulative sum). Over 52,608 half-hours this
  false-failed on a 5.1e-6 MWh solver-noise dip, not a real violation.
  Scaled it the same way.
- cli.py's summary printed net_of_opex_gbp under the label "Less fixed
  opex", so the terminal output showed the post-opex profit (£193k)
  where a reader would expect the opex figure itself (£15k). Split into
  two correctly-labelled lines.
- plots.py's monthly revenue chart stacked Market 1 (always negative
  here) and Market 2 (always positive) with a single running `bottom`,
  which is only correct for same-signed series: Market 2's bar
  completely overlapped and painted over Market 1's, hiding the
  -£297k Market 1 loss entirely. Now accumulates positive and negative
  contributions on separate baselines and marks the net.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-24 16:29:40 +01:00
co-authored by Claude Sonnet 5
parent afa02864a7
commit c70c9731a6
13 changed files with 52976 additions and 9 deletions
+4
View File
@@ -0,0 +1,4 @@
year,gross_profit_gbp,profit_market_1_gbp,profit_market_2_gbp,charged_mwh,discharged_mwh,equivalent_full_cycles,captured_spread_gbp_per_mwh
2018,67799.45428,-115113.361429,182912.815709,4096.144098,3696.77005,972.834224,18.340187
2019,64299.710798,-103884.584974,168184.295772,4944.211906,4459.443748,1173.537828,14.418774
2020,76331.687725,-78420.110711,154751.798435,5561.815889,5022.246341,1321.643774,15.198714
1 year gross_profit_gbp profit_market_1_gbp profit_market_2_gbp charged_mwh discharged_mwh equivalent_full_cycles captured_spread_gbp_per_mwh
2 2018 67799.45428 -115113.361429 182912.815709 4096.144098 3696.77005 972.834224 18.340187
3 2019 64299.710798 -103884.584974 168184.295772 4944.211906 4459.443748 1173.537828 14.418774
4 2020 76331.687725 -78420.110711 154751.798435 5561.815889 5022.246341 1321.643774 15.198714
Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

+52609
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

+37
View File
@@ -0,0 +1,37 @@
month,gross_profit_gbp,profit_market_1_gbp,profit_market_2_gbp,charged_mwh,discharged_mwh,equivalent_full_cycles,captured_spread_gbp_per_mwh
2018-01,5465.302553,-10616.512258,16081.814811,384.869784,343.548311,90.40745,15.908396
2018-02,5649.230748,-9703.961847,15353.192595,349.200387,318.950019,83.934215,17.711962
2018-03,8237.234668,-10604.237,18841.471667,396.015555,355.599039,93.578695,23.16439
2018-04,4806.727348,-9305.278306,14112.005654,360.263313,324.235141,85.325037,14.824819
2018-05,5511.866602,-9401.571826,14913.438427,370.694857,336.357109,88.515029,16.386948
2018-06,4846.162293,-8254.164575,13100.326868,344.023224,311.38346,81.943016,15.563326
2018-07,4733.333558,-10028.827592,14762.16115,352.885749,316.674389,83.335365,14.947005
2018-08,5369.799211,-10320.611101,15690.410312,325.781443,295.822752,77.848093,18.152083
2018-09,6294.844593,-8947.096603,15241.941196,306.195008,275.438495,72.483814,22.853903
2018-10,5998.14371,-7374.223128,13372.366838,305.310416,276.445151,72.748724,21.69741
2018-11,5658.950526,-9976.708879,15635.659404,308.559422,276.514059,72.766858,20.465327
2018-12,5227.858471,-10580.168315,15808.026786,292.344937,265.802125,69.947928,19.668234
2019-01,4846.091122,-9716.467684,14562.558806,301.096315,269.934425,71.035375,17.952846
2019-02,4386.850007,-9169.974804,13556.824811,354.872114,322.077084,84.757127,13.620497
2019-03,5685.537534,-9202.12936,14887.666893,395.787504,355.393223,93.524532,15.997878
2019-04,4718.922967,-9321.77924,14040.702207,366.770343,330.107734,86.870456,14.2951
2019-05,5427.961092,-9266.13638,14694.097472,424.406564,385.597895,101.47313,14.076739
2019-06,5106.284583,-8953.112834,14059.397417,431.412168,389.48601,102.496318,13.110316
2019-07,4410.738629,-10309.250217,14719.988846,455.116658,407.132784,107.140206,10.833661
2019-08,5371.192114,-7627.944384,12999.136498,411.497847,373.181806,98.205739,14.392963
2019-09,6108.180331,-6121.834754,12230.015085,446.080294,404.392466,106.41907,15.104585
2019-10,6225.554888,-7392.268463,13617.823351,460.993925,414.125371,108.980361,15.03302
2019-11,5546.450256,-9064.889778,14611.340034,417.26031,374.889076,98.65502,14.79491
2019-12,6465.947275,-7738.797076,14204.744351,478.917865,433.125873,113.980493,14.928564
2020-01,5752.783129,-6748.3924,12501.175529,469.180307,424.045227,111.590849,13.566438
2020-02,6045.669316,-5597.409405,11643.07872,446.676521,405.028061,106.586332,14.926544
2020-03,6146.118796,-6819.499809,12965.618605,494.105284,446.125018,117.401321,13.776674
2020-04,5671.636666,-5544.659957,11216.296623,482.833775,435.757483,114.673022,13.015581
2020-05,5591.88205,-5609.8907,11201.77275,518.380706,467.838587,123.115418,11.952588
2020-06,5305.6492,-5883.53861,11189.18781,491.564836,442.734765,116.509149,11.98381
2020-07,5152.114341,-6940.203845,12092.318187,513.960584,463.849427,122.065639,11.107299
2020-08,4740.600521,-9184.278367,13924.878888,479.188819,431.491892,113.550498,10.986534
2020-09,7591.825678,-6986.500821,14578.326499,397.581913,357.918912,94.189187,21.211021
2020-10,7291.309946,-7303.097011,14594.406957,443.701444,402.315335,105.872457,18.123371
2020-11,7836.211148,-5352.907107,13189.118256,436.922129,391.614722,103.056506,20.010001
2020-12,9205.886933,-6449.732679,15655.619612,387.71957,353.526912,93.033398,26.040131
1 month gross_profit_gbp profit_market_1_gbp profit_market_2_gbp charged_mwh discharged_mwh equivalent_full_cycles captured_spread_gbp_per_mwh
2 2018-01 5465.302553 -10616.512258 16081.814811 384.869784 343.548311 90.40745 15.908396
3 2018-02 5649.230748 -9703.961847 15353.192595 349.200387 318.950019 83.934215 17.711962
4 2018-03 8237.234668 -10604.237 18841.471667 396.015555 355.599039 93.578695 23.16439
5 2018-04 4806.727348 -9305.278306 14112.005654 360.263313 324.235141 85.325037 14.824819
6 2018-05 5511.866602 -9401.571826 14913.438427 370.694857 336.357109 88.515029 16.386948
7 2018-06 4846.162293 -8254.164575 13100.326868 344.023224 311.38346 81.943016 15.563326
8 2018-07 4733.333558 -10028.827592 14762.16115 352.885749 316.674389 83.335365 14.947005
9 2018-08 5369.799211 -10320.611101 15690.410312 325.781443 295.822752 77.848093 18.152083
10 2018-09 6294.844593 -8947.096603 15241.941196 306.195008 275.438495 72.483814 22.853903
11 2018-10 5998.14371 -7374.223128 13372.366838 305.310416 276.445151 72.748724 21.69741
12 2018-11 5658.950526 -9976.708879 15635.659404 308.559422 276.514059 72.766858 20.465327
13 2018-12 5227.858471 -10580.168315 15808.026786 292.344937 265.802125 69.947928 19.668234
14 2019-01 4846.091122 -9716.467684 14562.558806 301.096315 269.934425 71.035375 17.952846
15 2019-02 4386.850007 -9169.974804 13556.824811 354.872114 322.077084 84.757127 13.620497
16 2019-03 5685.537534 -9202.12936 14887.666893 395.787504 355.393223 93.524532 15.997878
17 2019-04 4718.922967 -9321.77924 14040.702207 366.770343 330.107734 86.870456 14.2951
18 2019-05 5427.961092 -9266.13638 14694.097472 424.406564 385.597895 101.47313 14.076739
19 2019-06 5106.284583 -8953.112834 14059.397417 431.412168 389.48601 102.496318 13.110316
20 2019-07 4410.738629 -10309.250217 14719.988846 455.116658 407.132784 107.140206 10.833661
21 2019-08 5371.192114 -7627.944384 12999.136498 411.497847 373.181806 98.205739 14.392963
22 2019-09 6108.180331 -6121.834754 12230.015085 446.080294 404.392466 106.41907 15.104585
23 2019-10 6225.554888 -7392.268463 13617.823351 460.993925 414.125371 108.980361 15.03302
24 2019-11 5546.450256 -9064.889778 14611.340034 417.26031 374.889076 98.65502 14.79491
25 2019-12 6465.947275 -7738.797076 14204.744351 478.917865 433.125873 113.980493 14.928564
26 2020-01 5752.783129 -6748.3924 12501.175529 469.180307 424.045227 111.590849 13.566438
27 2020-02 6045.669316 -5597.409405 11643.07872 446.676521 405.028061 106.586332 14.926544
28 2020-03 6146.118796 -6819.499809 12965.618605 494.105284 446.125018 117.401321 13.776674
29 2020-04 5671.636666 -5544.659957 11216.296623 482.833775 435.757483 114.673022 13.015581
30 2020-05 5591.88205 -5609.8907 11201.77275 518.380706 467.838587 123.115418 11.952588
31 2020-06 5305.6492 -5883.53861 11189.18781 491.564836 442.734765 116.509149 11.98381
32 2020-07 5152.114341 -6940.203845 12092.318187 513.960584 463.849427 122.065639 11.107299
33 2020-08 4740.600521 -9184.278367 13924.878888 479.188819 431.491892 113.550498 10.986534
34 2020-09 7591.825678 -6986.500821 14578.326499 397.581913 357.918912 94.189187 21.211021
35 2020-10 7291.309946 -7303.097011 14594.406957 443.701444 402.315335 105.872457 18.123371
36 2020-11 7836.211148 -5352.907107 13189.118256 436.922129 391.614722 103.056506 20.010001
37 2020-12 9205.886933 -6449.732679 15655.619612 387.71957 353.526912 93.033398 26.040131
+64
View File
@@ -0,0 +1,64 @@
{
"solver": {
"commit_hours": 24,
"degradation_cost_gbp_per_mwh": 0.0,
"milp_fallbacks": 1096,
"mode": "auto",
"window_hours": 48,
"windows": 1096
},
"summary": {
"average_captured_spread_gbp_per_mwh": 15.816025,
"capacity_end_mwh": 3.861279,
"capacity_retained_fraction": 0.96532,
"capacity_start_mwh": 4.0,
"charged_market_1_mwh": 11297.137749,
"charged_market_2_mwh": 3305.034144,
"cycle_budget": 5000.0,
"cycle_budget_used_fraction": 0.693603,
"days": 1096.0,
"discharged_market_1_mwh": 1952.341071,
"discharged_market_2_mwh": 11226.119067,
"end": "2020-12-31 23:30:00",
"energy_charged_from_grid_mwh": 14602.171893,
"energy_discharged_to_grid_mwh": 13178.460138,
"equivalent_full_cycles": 3468.015826,
"equivalent_full_cycles_per_year": 1155.741588,
"fixed_opex_gbp": 15003.422313,
"gross_profit_per_year_gbp": 69461.10309,
"gross_trading_profit_gbp": 208430.852803,
"half_hours": 52608,
"implied_life_years": 4.326227,
"net_of_opex_gbp": 193427.430489,
"profit_market_1_gbp": -297418.057114,
"profit_market_2_gbp": 505848.909916,
"profit_share_market_1": -1.426939,
"profit_share_market_2": 2.426939,
"round_trip_efficiency": 0.9025,
"start": "2018-01-01 00:00:00"
},
"validation": {
"checks": {
"charge_within_limit": true,
"discharge_within_limit": true,
"hourly_commitment_constant": true,
"no_simultaneous_charge_discharge": true,
"revenue_matches_prices_and_powers": true,
"soc_matches_power_flows": true,
"soc_within_bounds": true
},
"details": {
"hours_checked": 26304.0,
"max_hourly_commitment_gap_mw": 0.0,
"max_revenue_error_gbp": 0.0,
"max_soc_above_capacity_mwh": 0.000413531614,
"max_soc_below_zero_mwh": 5.101628e-06,
"max_soc_drift_mwh": 5.14322e-06,
"max_total_charge_mw": 2.00000005,
"max_total_discharge_mw": 2.0000001,
"simultaneous_half_hours": 0.0
},
"failures": [],
"ok": true
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB