Skip to content

Commit 355680d

Browse files
committed
feat(structural): genuine PMVR3 disclosure series unlocks TOKI period cohorts (measured)
Two operator-audited consecutive Park Mavera III cumulative-realized-sales disclosures (2019-10-31, 2019-11-30) added; the 2019-12-31 Level-2 case stays frozen. No new architecture; nothing fabricated. - The existing revision/reconciliation guards derived 4 VALID period cohorts at the room-type stratum level: Oct->Nov 2+1 (7 @ 1016244.2957) and 3+1 (2 @ 1435225.00); Nov->Dec 2+1 (5 @ 1003690.00) and 4+1 (1 @ 1684074.65). 3 strata are reconciliation-blocked (delta_count=0, delta_total!=0): 5+1 Oct->Nov; 3+1 & 5+1 Nov->Dec -- no division by zero, never reinterpreted as sales. 4+1 Oct->Nov (delta=0) yields no cohort. The overall TOTAL-row difference is never used as a clean cohort. - toki_cohort_moments moved unavailable -> AVAILABLE (toki_cohort_avg_price/count + room-type shares). dataset_status now reports reconciliation_blocked_strata. - HONEST MEASURED RESULT: these TOKI moments are now observed but have NO simulated counterpart in the current structural model (identification_report.observed_without_simulated_counterpart) -- a model-mapping gap, not a data gap, and no TOKI/primary-market mechanism was added. So rank(J_TOKI) stays 0, rank(J_combined) stays 2, and the status is unchanged NOT_IDENTIFIED (dim 6). Snapshot updated; the before->after comparison shows the 5 newly-unlocked TOKI moments with rank 2->2. - Level-2 real_records/toki.json unchanged; consumer path frozen; theta/optimizer/mechanism/thresholds/terminology untouched. - 177 tests passing (genuine PMVR3 cohort values asserted exactly)
1 parent 1c1537f commit 355680d

7 files changed

Lines changed: 113 additions & 11 deletions

File tree

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
[![Data refresh](https://github.com/onatozmenn/sold/actions/workflows/kfe-refresh.yml/badge.svg)](https://github.com/onatozmenn/sold/actions/workflows/kfe-refresh.yml)
55
[![Python](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/)
66
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
7-
[![Tests](https://img.shields.io/badge/tests-175%20passing-brightgreen.svg)](tests/)
7+
[![Tests](https://img.shields.io/badge/tests-177%20passing-brightgreen.svg)](tests/)
88
[![Data](https://img.shields.io/badge/data-TCMB%20%C2%B7%20T%C3%9C%C4%B0K-informational.svg)](#data-sources)
99

1010
> Infer the **realized transaction price** of a Turkish home from its **asking** price — a provenance-aware valuation engine.
@@ -301,7 +301,7 @@ tests/ # offline unit / end-to-end tests
301301
## Testing
302302

303303
```bash
304-
pytest -q # 175 tests, fully offline (no network or API key required)
304+
pytest -q # 177 tests, fully offline (no network or API key required)
305305
```
306306

307307
## Methodology & References
@@ -327,7 +327,8 @@ Negotiation-margin figures from Turkish market reporting: İstanbul ≈ 10%, Ank
327327
- [x] **Structural econometric core** — mechanism-aware generalized **Nash bargaining** (`P = ηB+(1−η)S`, `η` estimated, not hard-coded) fit by **Simulated Method of Moments**; TCMB-anchored hedonic fair value (relative premiums only, no listing intercept as level); structural UYAP auctions with the **statutory legal floor** (`muhammen_bedel` preserved as appraised value `Q`, never the reserve; partially-observed floors not fabricated); KAP `η`-calibration moments with a corporate mechanism shift; TOKİ cumulative-disclosure differencing into room-type cohort moments. Replaces weak-label aggregation as the core; the provenance registry and validated KAP/TOKİ/UYAP Level-2 records are kept; the consumer path is frozen as an optional future *validation* channel. No SaleProbability model yet
328328
- [x] **Statutory-floor fix, TCMB double-count audit & identification diagnostics** — corrected the İİK acceptance floor to `max(0.5·Q, priority_claims) + realization_costs`; audited the fair-value anchor so a contemporaneous TL/m² level is not trend-adjusted twice (KFE ratio only when rolling an older anchor); expanded the UYAP/KAP/TOKİ structural dataset schemas + observed-moment constructors (area semantics preserved, `log(sale/appraisal)` KAP moments, revision-guarded TOKİ cohorts); added `sold structural identify` (Jacobian rank / singular values / condition number / weak directions / profile diagnostics → `NOT_IDENTIFIED` → sensitivity mode)
329329
- [x] **Genuine structural dataset (measured, not synthetic)** — wired the three validated Level-2 records as the genuine audited seed under [`validation/structural/`](validation/structural/) (`source_audited=true`, kept distinct from fixtures): **1 UYAP auction** (sold; appraised `Q`=4.5M → winning 4.545M; parcel/net areas distinct, gross null; partial legal floor), **1 KAP negotiated disposal** (prior-appraisal 5.2M → sale 5.508M; `value_method=negotiation`), **1 TOKİ disclosure** (PMVR3 → **0** derivable period cohorts: differencing needs ≥2 consecutive disclosures). `m_obs` is rebuilt from this genuine data — **3 single-observation means** (`uyap_sale_prob`, `uyap_win/appraisal`, `kap log(sale/appraisal)`); variances/quantiles reported **unavailable** at n=1 (never guessed). Measured result: `sold structural dataset` + `sold structural identify` → **`NOT_IDENTIFIED`** (rank 2 / dim 6, condition number →∞), sensitivity mode; a three-way `WEAKLY_IDENTIFIED` status and moment-provenance/unavailability reporting were added
330-
- [x] **Identification-contribution diagnostics (source-specific Jacobian + snapshots)** — `sold structural identify` reports per-source Jacobian ranks (`J_UYAP`/`J_KAP`/`J_TOKİ`/`J_combined`) restricted to each family's genuinely observed moments — answering *which source adds an independent parameter direction* (a local moment-sensitivity diagnostic, **not** causal or standalone identification) — plus a `--save-snapshot` before→after comparison (newly-unlocked moments, sample-size increases, rank / smallest-non-zero-singular-value / condition-number / status deltas). **Measured on the current genuine data: `J_UYAP` rank 1 (`uyap_sale_prob` degenerate at 1.0), `J_KAP` rank 1, `J_TOKİ` rank 0 (single disclosure, no cohort), `J_combined` rank 2 → still `NOT_IDENTIFIED` (dim 6).** Unlocking `toki_cohort_moments` / `uyap_win-over-appraisal_sd` / `kap_log_ratio_sd` requires additional **genuine audited** records (a second consecutive PMVR3 disclosure; a second sold + one unsold UYAP auction; a second KAP negotiated disposal) — operator-supplied official records; none were fabricated, so those moments stay unavailable and the status is unchanged. The moment-unlock machinery is verified with clearly-labelled fixtures (not counted in the genuine report). **Next: operator-audited genuine records → rerun identify (data, not architecture)**
330+
- [x] **Identification-contribution diagnostics (source-specific Jacobian + snapshots)** — `sold structural identify` reports per-source Jacobian ranks (`J_UYAP`/`J_KAP`/`J_TOKİ`/`J_combined`) restricted to each family's genuinely observed moments — answering *which source adds an independent parameter direction* (a local moment-sensitivity diagnostic, **not** causal or standalone identification) — plus a `--save-snapshot` before→after comparison (newly-unlocked moments, sample-size increases, rank / smallest-non-zero-singular-value / condition-number / status deltas). **Measured on the current genuine data: `J_UYAP` rank 1 (`uyap_sale_prob` degenerate at 1.0), `J_KAP` rank 1, `J_TOKİ` rank 0 (single disclosure, no cohort), `J_combined` rank 2 → still `NOT_IDENTIFIED` (dim 6).** Unlocking `toki_cohort_moments` / `uyap_win-over-appraisal_sd` / `kap_log_ratio_sd` requires additional **genuine audited** records (a second consecutive PMVR3 disclosure; a second sold + one unsold UYAP auction; a second KAP negotiated disposal) — operator-supplied official records; none were fabricated, so those moments stay unavailable and the status is unchanged. The moment-unlock machinery is verified with clearly-labelled fixtures (not counted in the genuine report)
331+
- [x] **Genuine PMVR3 disclosure series → TOKİ period cohorts unlocked** — added two operator-audited consecutive Park Mavera III cumulative-realized-sales disclosures (`2019-10-31`, `2019-11-30`; the `2019-12-31` Level-2 case frozen). The existing revision/reconciliation guards derived **4 valid period cohorts** (Oct→Nov 2+1 & 3+1, Nov→Dec 2+1 & 4+1) and **reconciliation-blocked 3 strata** with `Δcount=0, Δtotal≠0` (5+1 Oct→Nov; 3+1 & 5+1 Nov→Dec — no division by zero, never reinterpreted as sales); the overall TOTAL-row difference is never used as a clean cohort. `toki_cohort_moments` moved **unavailable → available** (5 cohort/composition moments). **Honest measured result: these TOKİ moments are now observed but have _no simulated counterpart_ in the current structural model (a model-mapping gap, not a data gap — no new mechanism was added), so `rank(J_TOKİ)` stays 0, `rank(J_combined)` stays 2, and the status is unchanged `NOT_IDENTIFIED`.** Mapping TOKİ primary-market moments to `θ` is a deliberately-deferred future structural-model extension
331332
- [ ] **SaleProbability** model (`P(sold ≤ N days)`) trained on collected outcomes
332333
- [ ] Live, ToS-reviewed fetchers for the public label sources
333334
- [ ] Broker-vs-benchmark analytics over an aggregate anonymized dataset

src/sold/cli.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1513,7 +1513,8 @@ def structural_dataset_cmd() -> None:
15131513
)
15141514
typer.echo(
15151515
f" geçerli dönem kohortu {t['valid_derived_period_cohorts']} "
1516-
f"· revizyonla-bloklanan {t['revision_blocked_cohorts']}"
1516+
f"· revizyonla-bloklanan {t['revision_blocked_cohorts']} "
1517+
f"· mutabakatla-bloklanan strata {t.get('reconciliation_blocked_strata', 0)}"
15171518
)
15181519
na = st["non_audited_records"]
15191520
typer.secho(
@@ -1618,6 +1619,12 @@ def structural_identify_cmd(
16181619
typer.echo(f" Moment provenance: {rep['moment_provenance']}")
16191620
for un in rep.get("unavailable_moments", []):
16201621
typer.echo(f" Eksik moment: {un['moment']} [{un['source']}] — {un['reason']}")
1622+
owc = rep.get("observed_without_simulated_counterpart", [])
1623+
if owc:
1624+
typer.secho(
1625+
f" Gözlenen ama sim KARŞILIĞI YOK (model-eşleme boşluğu; Jacobian'a girmez): {owc}",
1626+
fg=typer.colors.YELLOW,
1627+
)
16211628
color = {
16221629
"IDENTIFIED": typer.colors.GREEN,
16231630
"WEAKLY_IDENTIFIED": typer.colors.YELLOW,

src/sold/structural/datasets.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ def _toki_status(disclosures: list[dict], toki_result: dict) -> dict:
103103
"room_type_cumulative_strata": int(strata),
104104
"valid_derived_period_cohorts": int(len(toki_result.get("cohorts", []))),
105105
"revision_blocked_cohorts": int(len(toki_result.get("revisions", []))),
106+
"reconciliation_blocked_strata": int(len(toki_result.get("reconciliation", []))),
106107
}
107108

108109

src/sold/structural/identify.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,10 @@ def identification_report(
229229
)
230230
dim = len(free_names)
231231
n_moments = len(keys)
232+
# GÖZLENEN ama mevcut yapısal modelde SİMÜLE KARŞILIĞI OLMAYAN momentler (ör. TOKİ
233+
# kohort momentleri): m_obs'ta VAR ama Jacobian'a GİRMEZ — çünkü simülatör bu
234+
# mekanizmayı (henüz) üretmez. Bu bir MODEL-eşleme boşluğudur (veri değil), dürüstçe raporlanır.
235+
observed_unmatched = sorted(k for k in (m_obs or {}) if k not in set(keys))
232236

233237
report: dict = {
234238
"dataset": summary,
@@ -238,6 +242,7 @@ def identification_report(
238242
"moment_keys": keys,
239243
"moment_provenance": provenance or {},
240244
"unavailable_moments": unavailable or [],
245+
"observed_without_simulated_counterpart": observed_unmatched,
241246
"sample_sizes": sample_sizes or {},
242247
"jacobian_step": step,
243248
}

tests/test_structural.py

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -462,9 +462,10 @@ def test_genuine_datasets_load_and_reconcile_with_level2():
462462
assert k["sale_price"] == 5_508_474.60 and k["appraisal_value"] == 5_200_000
463463
assert k["reference_price_type"] == "prior_appraisal"
464464
assert bool(k["negotiated"]) is True and bool(k["related_party"]) is False
465-
# TOKİ: 1 disclosure → 0 dönem kohortu (tek disclosure farklanamaz)
466-
assert len(g["toki_disclosures"]) == 1
467-
assert g["toki_result"]["cohorts"] == []
465+
# TOKİ: 3 ardışık denetlenmiş disclosure → 4 geçerli dönem kohortu (mutabakat-bloklu strata hariç)
466+
assert len(g["toki_disclosures"]) == 3
467+
assert len(g["toki_result"]["cohorts"]) == 4
468+
assert g["toki_result"]["revision_detected"] is False
468469

469470

470471
def test_dataset_status_genuine_counts():
@@ -475,7 +476,9 @@ def test_dataset_status_genuine_counts():
475476
assert g["kap"]["audited_eligible_disposals"] == 1
476477
assert g["kap"]["negotiated_calibration_observations"] == 1
477478
assert g["kap"]["prior_appraisal_observations"] == 1 and g["kap"]["appraisal_observations"] == 0
478-
assert g["toki"]["audited_disclosures"] == 1 and g["toki"]["valid_derived_period_cohorts"] == 0
479+
assert g["toki"]["audited_disclosures"] == 3
480+
assert g["toki"]["valid_derived_period_cohorts"] == 4
481+
assert g["toki"]["reconciliation_blocked_strata"] == 3
479482
assert st["non_audited_records"]["uyap"] == 0
480483

481484

@@ -500,7 +503,8 @@ def test_build_observed_moments_reports_provenance_and_unavailable():
500503
un_moments = {u["moment"] for u in un}
501504
assert "uyap_win_over_appraisal_sd" in un_moments # n=1 sold
502505
assert "kap_log_ratio_sd" in un_moments # n=1 negotiated
503-
assert "toki_cohort_moments" in un_moments # 0 cohorts
506+
# TOKİ kohort momenti artık AVAILABLE (3 gerçek disclosure → 4 kohort), unavailable DEĞİL
507+
assert "toki_cohort_avg_price" in m and "toki_cohort_moments" not in un_moments
504508
assert m["kap_log_ratio_mean"] == pytest.approx(np.log(5_508_474.60 / 5_200_000), abs=1e-6)
505509

506510

@@ -644,3 +648,47 @@ def test_second_kap_unlocks_log_ratio_sd_fixture():
644648
)
645649
built = build_observed_moments(None, df, None)
646650
assert "kap_log_ratio_sd" in built["moments"] # ≥2 müzakereli → sd AÇILDI
651+
652+
653+
# --- GERÇEK PMVR3 serisi (3 denetlenmiş disclosure) dönem kohortları ---------- #
654+
def test_genuine_pmvr3_series_derives_expected_cohorts():
655+
g = load_genuine_datasets()
656+
res = g["toki_result"]
657+
assert res["revision_detected"] is False
658+
cohorts = {(c["period_start"], c["period_end"], c["room_type"]): c for c in res["cohorts"]}
659+
# Oct→Nov geçerli
660+
c = cohorts[("2019-10-31", "2019-11-30", "2+1")]
661+
assert c["cohort_count"] == 7 and c["cohort_total"] == pytest.approx(7113710.07)
662+
assert c["cohort_avg"] == pytest.approx(1016244.2957142857)
663+
c = cohorts[("2019-10-31", "2019-11-30", "3+1")]
664+
assert c["cohort_count"] == 2 and c["cohort_avg"] == pytest.approx(1435225.00)
665+
# Nov→Dec geçerli
666+
c = cohorts[("2019-11-30", "2019-12-31", "2+1")]
667+
assert c["cohort_count"] == 5 and c["cohort_avg"] == pytest.approx(1003690.00)
668+
c = cohorts[("2019-11-30", "2019-12-31", "4+1")]
669+
assert c["cohort_count"] == 1 and c["cohort_avg"] == pytest.approx(1684074.65)
670+
assert len(res["cohorts"]) == 4 # 4+1 Oct→Nov (delta=0) kohort DEĞİL
671+
# mutabakat-bloklu (delta_count=0 & delta_total≠0): 5+1 Oct→Nov, 3+1 & 5+1 Nov→Dec
672+
recon = {(r["room_type"], r["period_end"]) for r in res["reconciliation"]}
673+
assert ("5+1", "2019-11-30") in recon
674+
assert ("3+1", "2019-12-31") in recon
675+
assert ("5+1", "2019-12-31") in recon
676+
assert len(res["reconciliation"]) == 3
677+
678+
679+
def test_genuine_toki_moment_available_but_no_sim_counterpart():
680+
# TOKİ kohort momenti artık AÇIK, ama mevcut modelde sim KARŞILIĞI YOK → J_TOKI rank 0
681+
g = load_genuine_datasets()
682+
built = build_observed_moments(g["uyap"], g["kap"], g["toki_result"])
683+
assert "toki_cohort_avg_price" in built["moments"]
684+
assert built["provenance"]["toki_cohort_avg_price"] == "toki"
685+
ctx = context_from_datasets(g["uyap"], g["kap"])
686+
rep = identification_report(
687+
ctx, StructuralParams(), DEFAULT_FREE, m_obs=built["moments"],
688+
auctions=g["uyap"], kap=g["kap"], toki_result=g["toki_result"],
689+
provenance=built["provenance"],
690+
)
691+
assert "toki_cohort_avg_price" in rep["observed_without_simulated_counterpart"]
692+
assert rep["source_jacobians"]["J_TOKI"]["rank"] == 0 # sim karşılığı yok
693+
assert rep["source_jacobians"]["J_combined"]["rank"] == 2 # değişmedi
694+
assert rep["status"] == "NOT_IDENTIFIED"

validation/structural/identify_snapshot.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
"n_observed_moments": 3,
44
"available_moments": [
55
"kap_log_ratio_mean",
6+
"toki_cohort_avg_price",
7+
"toki_cohort_count",
8+
"toki_share_2+1",
9+
"toki_share_3+1",
10+
"toki_share_4+1",
611
"uyap_sale_prob",
712
"uyap_win_over_appraisal_mean"
813
],
@@ -12,7 +17,12 @@
1217
"uyap_win_over_appraisal_sd": 1,
1318
"kap_log_ratio_mean": 1,
1419
"kap_log_ratio_sd": 1,
15-
"toki_cohort_moments": 0
20+
"toki_cohort_moments": 4,
21+
"toki_cohort_avg_price": 4,
22+
"toki_cohort_count": 4,
23+
"toki_share_2+1": 4,
24+
"toki_share_3+1": 4,
25+
"toki_share_4+1": 4
1626
},
1727
"rank": 2,
1828
"smallest_nonzero_singular_value": 0.5793385803552313,

validation/structural/toki.json

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,42 @@
11
[
2+
{
3+
"project_id": "PMVR3",
4+
"as_of_date": "2019-10-31",
5+
"observation_role": "cumulative_realized_sales",
6+
"table_semantics": "cumulative_realized_sales_by_room_type",
7+
"source_audited": true,
8+
"_validation_ref": "operator-audited PMVR3 official disclosure series (2019-10-31)",
9+
"_note": "GENUINE manually-audited official Park Mavera III (PMVR3) cumulative realized-sales disclosure, as-of 2019-10-31, same published disclosure series and table semantics as the frozen 2019-12-31 Level-2 record. Operator-audited official table values supplied as structured fields; the aggregate adapter normalizes them — the system does NOT claim raw-PDF extraction. Official TOTAL row (audit only, NOT used for differencing): count=372 total_price=359650908.98 total_gross_m2=67112.34 average_price=966803.52 average_m2_price=5358.94.",
10+
"strata": [
11+
{"room_type": "2+1", "count": 153, "total_price": 106285859.62, "total_gross_m2": 20461.86, "average_price": 694678.82, "average_m2_price": 5194.34, "cum_count": 153, "cum_total": 106285859.62},
12+
{"room_type": "3+1", "count": 76, "total_price": 74899258.35, "total_gross_m2": 14202.85, "average_price": 982516.56, "average_m2_price": 5273.54, "cum_count": 76, "cum_total": 74899258.35},
13+
{"room_type": "4+1", "count": 23, "total_price": 27248070.90, "total_gross_m2": 4935.96, "average_price": 1184698.73, "average_m2_price": 5520.77, "cum_count": 23, "cum_total": 27248070.90},
14+
{"room_type": "5+1", "count": 120, "total_price": 151217720.11, "total_gross_m2": 27511.67, "average_price": 1260147.67, "average_m2_price": 5496.49, "cum_count": 120, "cum_total": 151217720.11}
15+
]
16+
},
17+
{
18+
"project_id": "PMVR3",
19+
"as_of_date": "2019-11-30",
20+
"observation_role": "cumulative_realized_sales",
21+
"table_semantics": "cumulative_realized_sales_by_room_type",
22+
"source_audited": true,
23+
"_validation_ref": "operator-audited PMVR3 official disclosure series (2019-11-30)",
24+
"_note": "GENUINE manually-audited official Park Mavera III (PMVR3) cumulative realized-sales disclosure, as-of 2019-11-30, same published disclosure series and table semantics as the frozen 2019-12-31 Level-2 record. Operator-audited official table values supplied as structured fields; the aggregate adapter normalizes them — the system does NOT claim raw-PDF extraction. Official TOTAL row (audit only, NOT used for differencing): count=381 total_price=375610239.03 total_gross_m2=68424.69 average_price=985853.65 average_m2_price=5489.40.",
25+
"strata": [
26+
{"room_type": "2+1", "count": 160, "total_price": 113399569.69, "total_gross_m2": 21408.07, "average_price": 708747.31, "average_m2_price": 5297.05, "cum_count": 160, "cum_total": 113399569.69},
27+
{"room_type": "3+1", "count": 78, "total_price": 77769708.35, "total_gross_m2": 14568.99, "average_price": 997047.54, "average_m2_price": 5338.03, "cum_count": 78, "cum_total": 77769708.35},
28+
{"room_type": "4+1", "count": 23, "total_price": 27248070.90, "total_gross_m2": 4935.96, "average_price": 1184698.73, "average_m2_price": 5520.77, "cum_count": 23, "cum_total": 27248070.90},
29+
{"room_type": "5+1", "count": 120, "total_price": 157192890.09, "total_gross_m2": 27511.67, "average_price": 1309940.75, "average_m2_price": 5713.68, "cum_count": 120, "cum_total": 157192890.09}
30+
]
31+
},
232
{
333
"project_id": "PMVR3",
434
"as_of_date": "2019-12-31",
535
"observation_role": "cumulative_realized_sales",
636
"table_semantics": "cumulative_realized_sales_by_room_type",
737
"source_audited": true,
838
"_validation_ref": "validation/real_records/toki.json",
9-
"_note": "GENUINE audited TOKİ disclosure derived from validated Level-2 Park Mavera III (PMVR3) aggregate record. This is a SINGLE disclosure (one as-of date); repeated consecutive disclosures for the SAME project are required to difference cumulative strata into period cohorts, so ZERO period cohorts can be derived from this alone. The offered_inventory population is NOT paired with realized sales (different populations); only the cumulative_realized_sales strata are carried for future period differencing.",
39+
"_note": "GENUINE audited TOKİ disclosure derived from validated Level-2 Park Mavera III (PMVR3) aggregate record (FROZEN Level-2 case). Now the third point in a consecutive PMVR3 cumulative-realized-sales series (with 2019-10-31 and 2019-11-30); the audited cumulative strata values remain unchanged. The offered_inventory population is NOT paired with realized sales; only cumulative_realized_sales strata are carried for period differencing.",
1040
"strata": [
1141
{"room_type": "2+1", "cum_count": 165, "cum_total": 118418019.69},
1242
{"room_type": "3+1", "cum_count": 78, "cum_total": 78003128.35},

0 commit comments

Comments
 (0)