PRICE-02: the trading verdict skips price periods that have ended #206
@@ -68,33 +68,25 @@ A, B = "inverter-a", "inverter-b"
|
||||
print("1. modes off: byte-identical to 7a00f12 on the trade path")
|
||||
# Printed on release/1.0 7a00f12 (2026-09-29), goodwe-addon-checks:1, 1080
|
||||
# cycles each; the trade CHARGEs and DISCHARGEs. PRICE-02 (2026-10-22): the
|
||||
# digest is over every row with the trade's SENTENCE left out (action and
|
||||
# watts stay). The plan now drops price periods that have ended, so the
|
||||
# sentence of a sale quotes a smaller "above the cheapest" figure once the
|
||||
# first cheap period is over, and the idle sentence says "price period".
|
||||
# Re-measured on 7a00f12, on release/1.0 90bc901 and on this tree: the same
|
||||
# four digests, so no command, integrator or allocation moved.
|
||||
# digest is `ident.trade_digest()`, which hides two things in the trade
|
||||
# sentence: the "above the cheapest" figure (the plan now drops price periods
|
||||
# that have ended, so it is another number once the first cheap period is
|
||||
# over) and "hour" -> "price period". Re-measured with it on 7a00f12, on
|
||||
# release/1.0 90bc901 and on this tree: the same four digests.
|
||||
AT_7A00F12 = {
|
||||
"n1": "2f3cf03655f19a172e83ccae1e1308a8eef9d1023ab632a68b943920b032800d",
|
||||
"n2": "59ba1cbfe33aeca74d96b50dbcfde5337a8f82de0fde598a048afeef46fe64de",
|
||||
"n1_off": "2f3cf03655f19a172e83ccae1e1308a8eef9d1023ab632a68b943920b032800d",
|
||||
"n2_off": "59ba1cbfe33aeca74d96b50dbcfde5337a8f82de0fde598a048afeef46fe64de",
|
||||
"n1": "33886ef03f364852883f0370230e6e04823fbb46a4704f88ca75bf9082d98c01",
|
||||
"n2": "666a31f41491c22750720524853d95944d5fba395d1d14040c460d71414b275f",
|
||||
"n1_off": "33886ef03f364852883f0370230e6e04823fbb46a4704f88ca75bf9082d98c01",
|
||||
"n2_off": "666a31f41491c22750720524853d95944d5fba395d1d14040c460d71414b275f",
|
||||
}
|
||||
|
||||
|
||||
def _cmd_digest(rows):
|
||||
"""`ident.digest()` over rows whose trade is (action, watts) only."""
|
||||
return ident.digest([r[:-1] + (None if r[-1] is None else r[-1][:2],)
|
||||
for r in rows])
|
||||
|
||||
|
||||
_cmd_digest = ident.trade_digest
|
||||
_rows = {k: ident.run(**ident.SCENARIOS[k])[0] for k in AT_7A00F12}
|
||||
_got = {k: _cmd_digest(v) for k, v in _rows.items()}
|
||||
for k in AT_7A00F12:
|
||||
print(f" {k} {'same' if _got[k] == AT_7A00F12[k] else 'DIFFERS'} "
|
||||
f"{_got[k][:16]}")
|
||||
check("with battery modes off (option absent or false), every command, "
|
||||
"integrator, allocation and trade action equals 7a00f12's, at one "
|
||||
"integrator, allocation and trade sentence equals 7a00f12's, at one "
|
||||
"inverter and at two", _got == AT_7A00F12)
|
||||
_acts = {r[-1][0] for r in _rows["n2"] if r[-1]}
|
||||
check("...and the runs reach the trade P3 now skips with modes on: a charge "
|
||||
|
||||
@@ -596,17 +596,22 @@ check("selling is off: no sale on any cycle",
|
||||
|
||||
# ============================================================================ #
|
||||
print("\n5. modes off: byte-identical to release/1.0 e3e4ba6")
|
||||
# Printed by tools/opt11p3_identity.py on release/1.0 e3e4ba6 (2026-10-13),
|
||||
# goodwe-addon-checks:1, with this branch's harness (same API). n1 and n2 are
|
||||
# also 5a4cdc2's; the lag ones moved with SAFETY-90/91 (n2_lag now equals n2:
|
||||
# the next-quarter grading removed the edge tick's blindness at N=2).
|
||||
# Printed on release/1.0 e3e4ba6 (2026-10-13), goodwe-addon-checks:1, with this
|
||||
# branch's harness (same API). n1 and n2 are also 5a4cdc2's; the lag ones moved
|
||||
# with SAFETY-90/91 (n2_lag now equals n2: the next-quarter grading removed the
|
||||
# edge tick's blindness at N=2). PRICE-02 (2026-10-22): the digest is
|
||||
# `ident.trade_digest()`, which hides two things in the trade sentence: the
|
||||
# "above the cheapest" figure (the plan now drops price periods that have
|
||||
# ended) and "hour" -> "price period". Re-measured with it on e3e4ba6, on
|
||||
# release/1.0 90bc901 and on this tree: the same four digests.
|
||||
AT_BASE = {
|
||||
"n1": "71245b227ca40bada4f71f57ea6154475f4b0bd60239c9ad4f80bffb0094514c",
|
||||
"n2": "56cf28010b06765c29e5479abb815d7503d570b39240d82dfc818efa90c93722",
|
||||
"n1_lag": "86ef0f5ad8da1498ff7dcf59262a177bef847a0b201ce804e947c8eab5f07190",
|
||||
"n2_lag": "56cf28010b06765c29e5479abb815d7503d570b39240d82dfc818efa90c93722",
|
||||
"n1": "33886ef03f364852883f0370230e6e04823fbb46a4704f88ca75bf9082d98c01",
|
||||
"n2": "666a31f41491c22750720524853d95944d5fba395d1d14040c460d71414b275f",
|
||||
"n1_lag": "f6c67b351bd732fb69e62cafbfdb2bcff6032f5d8845836659d096b8c677d3c0",
|
||||
"n2_lag": "666a31f41491c22750720524853d95944d5fba395d1d14040c460d71414b275f",
|
||||
}
|
||||
_got = {k: ident.digest(ident.run(**ident.SCENARIOS[k])[0])
|
||||
_cmd_digest = ident.trade_digest
|
||||
_got = {k: _cmd_digest(ident.run(**ident.SCENARIOS[k])[0])
|
||||
for k in AT_BASE}
|
||||
for _k in AT_BASE:
|
||||
print(f" {_k} {'same' if _got[_k] == AT_BASE[_k] else 'DIFFERS'} "
|
||||
@@ -619,7 +624,7 @@ _real_project = tariff.PeakTracker.project
|
||||
tariff.PeakTracker.project = staticmethod(
|
||||
lambda a, now, roll=False: _real_project(a, now, roll=True))
|
||||
try:
|
||||
_moved = ident.digest(ident.run(**ident.SCENARIOS["n1_lag"])[0]) \
|
||||
_moved = _cmd_digest(ident.run(**ident.SCENARIOS["n1_lag"])[0]) \
|
||||
!= AT_BASE["n1_lag"]
|
||||
finally:
|
||||
tariff.PeakTracker.project = _real_project
|
||||
|
||||
@@ -17,6 +17,7 @@ test_modes_p3.py part 1 holds this tree to the digests printed on 7a00f12.
|
||||
import functools
|
||||
import hashlib
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
@@ -117,6 +118,28 @@ def digest(rows) -> str:
|
||||
return hashlib.sha256(repr(rows).encode()).hexdigest()
|
||||
|
||||
|
||||
def _trade_words(text):
|
||||
"""PRICE-02: the trade sentence as release/1.0 before it printed it. The
|
||||
plan now drops price periods that have ended, so a sale's "above the
|
||||
cheapest" figure is a different number once the first cheap period is
|
||||
over, and the sentences say "price period" where they said "hour". Both
|
||||
maps are applied to both sides, so only those two things are hidden."""
|
||||
text = text.replace("this hour is neither the buy hour nor the sell hour",
|
||||
"now is not the cheapest or the dearest price period")
|
||||
text = re.sub(r"[0-9]+\.[0-9]+ above the cheapest",
|
||||
"N above the cheapest", text)
|
||||
return text.replace("firm hour at", "firm price period at")
|
||||
|
||||
|
||||
def trade_digest(rows) -> str:
|
||||
"""`digest()` with the trade sentence passed through `_trade_words()`:
|
||||
every command, integrator and allocation, and the action, watts and the
|
||||
rest of the sentence, byte for byte."""
|
||||
return digest([r[:-1] + (None if r[-1] is None else
|
||||
(r[-1][0], r[-1][1], _trade_words(r[-1][2])),)
|
||||
for r in rows])
|
||||
|
||||
|
||||
def digests() -> dict:
|
||||
return {k: digest(run(**v)[0]) for k, v in SCENARIOS.items()}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user