Compare commits
10 Commits
6f6d6b8047
...
9263283995
| Author | SHA1 | Date | |
|---|---|---|---|
| 9263283995 | |||
| 6536c9903e | |||
| 02aa750a06 | |||
| 2bbe4e58ec | |||
| d2ff607c79 | |||
| e28f8fcf85 | |||
| 3fbf332b31 | |||
| 328855a926 | |||
| 89674c24dd | |||
| 9f666538c3 |
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -9,3 +9,4 @@ fundlab/nport_cache/raw/
|
||||||
fundlab/universe_cache/
|
fundlab/universe_cache/
|
||||||
fundlab/xcheck_run.log
|
fundlab/xcheck_run.log
|
||||||
fundlab/streamlit.log
|
fundlab/streamlit.log
|
||||||
|
reports/report_data_adhoc.json
|
||||||
|
|
|
||||||
253
app.py
253
app.py
|
|
@ -403,6 +403,17 @@ def rng(s):
|
||||||
"""Clip a price/return series (or frame) to the display range."""
|
"""Clip a price/return series (or frame) to the display range."""
|
||||||
return s[(s.index >= lo) & (s.index <= hi)]
|
return s[(s.index >= lo) & (s.index <= hi)]
|
||||||
|
|
||||||
|
# standalone symbols in the Symbol box (not portfolio components) get a
|
||||||
|
# full per-fund report, built on demand - point the user at it
|
||||||
|
_standalone = [s for w in items if len(w) == 1 for s in w]
|
||||||
|
if _standalone:
|
||||||
|
st.info(
|
||||||
|
f"Full report(s) generated for: "
|
||||||
|
f"{', '.join(s.upper() for s in _standalone)} — see the "
|
||||||
|
f"**Fund Lab** tab, top of the Summary section. (Only symbols "
|
||||||
|
f"that stand alone in the Symbol box get a report; portfolio "
|
||||||
|
f"components do not.)")
|
||||||
|
|
||||||
tab_stats, tab_equity, tab_alloc, tab_tax, tab_corr, tab_fundlab = st.tabs(
|
tab_stats, tab_equity, tab_alloc, tab_tax, tab_corr, tab_fundlab = st.tabs(
|
||||||
["Statistics", "Equity curves", "Allocation", "Tax detail",
|
["Statistics", "Equity curves", "Allocation", "Tax detail",
|
||||||
"Correlation", "Fund Lab"])
|
"Correlation", "Fund Lab"])
|
||||||
|
|
@ -576,6 +587,110 @@ with tab_corr:
|
||||||
|
|
||||||
# ---------------------------------------------------------------- fund lab
|
# ---------------------------------------------------------------- fund lab
|
||||||
# per-fund report mockup from N-PORT schedules of investments (fundlab)
|
# per-fund report mockup from N-PORT schedules of investments (fundlab)
|
||||||
|
|
||||||
|
def render_fund_report(_f: dict) -> None:
|
||||||
|
"""Render one per-fund report entry (narrative, re-basing equity
|
||||||
|
chart, period table, drivers, reference mix, tax, cluster peers).
|
||||||
|
Used by the Summary section for both the pre-built 24 and the
|
||||||
|
on-demand reports generated for standalone Symbol-box funds."""
|
||||||
|
_m, _st = _f["meta"], _f.get("stats", {})
|
||||||
|
_grp = {"candidate": "C", "shortlist": "S"}.get(_m["group"], "A")
|
||||||
|
# ad-hoc entries carry negative sort orders (they sort first) - show
|
||||||
|
# the absolute number; and skip the name when it just repeats the
|
||||||
|
# ticker (ETFs have no fund name on file)
|
||||||
|
_num = abs(int(_m["order"]))
|
||||||
|
_nm = _m["name"] if _m["name"].upper() != _m["sym"].upper() else None
|
||||||
|
_title = (f"{_grp}{_num:02d} · {_m['sym'].upper()}"
|
||||||
|
+ (f" — {_nm}" if _nm else ""))
|
||||||
|
if _m.get("verdict"):
|
||||||
|
_title += f" [{_m['verdict'][:44]}]"
|
||||||
|
with st.expander(_title):
|
||||||
|
if _f.get("narrative"):
|
||||||
|
st.markdown("\n\n".join(_f["narrative"]))
|
||||||
|
# same re-basing-on-zoom widget as the Equity curves tab: every
|
||||||
|
# visible window re-bases each line to 1.0 at its left edge, so
|
||||||
|
# fund/reference/index are comparable no matter where you zoom
|
||||||
|
_c = _f.get("chart", {})
|
||||||
|
if _c.get("dates"):
|
||||||
|
from chart_widget import equity_chart_html
|
||||||
|
_ds = pd.to_datetime(_c["dates"])
|
||||||
|
_series = {_m["sym"].upper(): pd.Series(_c["fund"], _ds)}
|
||||||
|
if _c.get("ref"):
|
||||||
|
_series["fitted reference"] = pd.Series(
|
||||||
|
_c["ref"], pd.to_datetime(_c["ref_dates"]))
|
||||||
|
if _c.get("ivv"):
|
||||||
|
_series["S&P 500 (IVV)"] = pd.Series(
|
||||||
|
_c["ivv"], pd.to_datetime(_c["ivv_dates"]))
|
||||||
|
st.iframe(equity_chart_html(
|
||||||
|
{k: s / s.iloc[0] for k, s in _series.items()},
|
||||||
|
_ds, height=460, ytitle="growth (1.0 = start)",
|
||||||
|
styles={
|
||||||
|
_m["sym"].upper(): {"width": 2},
|
||||||
|
"fitted reference": {"width": 1, "dash": "dash",
|
||||||
|
"opacity": 0.8},
|
||||||
|
"S&P 500 (IVV)": {"width": 1, "dash": "dot",
|
||||||
|
"opacity": 0.5},
|
||||||
|
}), height=490)
|
||||||
|
if _f.get("perf"):
|
||||||
|
st.dataframe(pd.DataFrame(
|
||||||
|
_f["perf"],
|
||||||
|
columns=["period", "fund", "reference",
|
||||||
|
"S&P 500", "fund − reference"]),
|
||||||
|
width="stretch", hide_index=True)
|
||||||
|
st.caption(
|
||||||
|
"fund − reference = period alpha/timing (the part of "
|
||||||
|
"that period the fitted mix does not explain). For "
|
||||||
|
"cash-anchored funds the reference is the T-bill rate "
|
||||||
|
"itself.")
|
||||||
|
if _f.get("drivers"):
|
||||||
|
st.markdown("\n\n".join(_f["drivers"]))
|
||||||
|
_sty = _f.get("style")
|
||||||
|
if _sty and _sty.get("full"):
|
||||||
|
_f5 = {x["sym"]: x for x in _sty.get("rec5", {}).get("factors", [])}
|
||||||
|
_srows = []
|
||||||
|
for x in _sty["full"]["factors"]:
|
||||||
|
y5 = _f5.get(x["sym"], {})
|
||||||
|
if abs(x["t"]) < 2 and abs(y5.get("t", 0) or 0) < 2:
|
||||||
|
continue
|
||||||
|
_srows.append([
|
||||||
|
x["name"], f"{x['beta']:+.2f}", f"{x['t']:+.1f}",
|
||||||
|
(f"{y5['beta']:+.2f}" if y5 else "—"),
|
||||||
|
(f"{y5['t']:+.1f}" if y5 else "—"),
|
||||||
|
"✓" if x["sym"] in _sty.get("identified", []) else ""])
|
||||||
|
st.markdown("**Style tilts** (22 style/asset sleeves regressed "
|
||||||
|
"on the fund's excess returns; US funds proxy the "
|
||||||
|
"global factors; 'identified' = survived the BIC "
|
||||||
|
"forward-selection gate on the full history)")
|
||||||
|
st.dataframe(pd.DataFrame(
|
||||||
|
_srows,
|
||||||
|
columns=["factor", "β full", "t full", "β 5y", "t 5y",
|
||||||
|
"identified"]),
|
||||||
|
width="stretch", hide_index=True)
|
||||||
|
st.markdown("\n\n".join(_sty.get("commentary", [])))
|
||||||
|
_ref = _f.get("reference")
|
||||||
|
if _ref and _ref.get("rows"):
|
||||||
|
st.markdown(f"**Reference mix** ({_ref['netcash']})")
|
||||||
|
st.dataframe(pd.DataFrame(
|
||||||
|
_ref["rows"],
|
||||||
|
columns=["loading", "what it is",
|
||||||
|
"what it exposes you to"]),
|
||||||
|
width="stretch", hide_index=True)
|
||||||
|
st.caption(_ref["text"])
|
||||||
|
if _f.get("tax"):
|
||||||
|
st.markdown(f"**Tax** — {_f['tax']}")
|
||||||
|
_pe = _f.get("peers")
|
||||||
|
if _pe and _pe.get("rows"):
|
||||||
|
st.markdown(
|
||||||
|
f"**Peers — cluster: {_pe['cluster']}** "
|
||||||
|
f"(n={_pe['n']})")
|
||||||
|
st.dataframe(pd.DataFrame(
|
||||||
|
_pe["rows"],
|
||||||
|
columns=["fund", "5y", "CAGR", "maxDD",
|
||||||
|
"R² 5y", "alpha 5y", "tax"]),
|
||||||
|
width="stretch", hide_index=True)
|
||||||
|
st.caption(_pe["proscons"])
|
||||||
|
|
||||||
|
|
||||||
with tab_fundlab:
|
with tab_fundlab:
|
||||||
try:
|
try:
|
||||||
_FUNDS = json.loads((Path(__file__).parent / "funds.json").read_text())
|
_FUNDS = json.loads((Path(__file__).parent / "funds.json").read_text())
|
||||||
|
|
@ -595,25 +710,74 @@ with tab_fundlab:
|
||||||
_DR = json.loads(_dc.RESULTS.read_text())
|
_DR = json.loads(_dc.RESULTS.read_text())
|
||||||
except Exception:
|
except Exception:
|
||||||
_DR = {}
|
_DR = {}
|
||||||
with st.expander(f"Summary — all {len(_FL_LABELS)} funds"):
|
# --- per-fund report: narrative + performance + drivers + peers ----
|
||||||
_sum_rows = []
|
# static build (fundlab.reportdata) so the page stays fast
|
||||||
for _s in _ORDER:
|
_RD = Path(__file__).parent / "reports" / "report_data.json"
|
||||||
_d = _DR.get(_s, {})
|
if not _RD.exists():
|
||||||
_rec = _d.get("recent", {})
|
with st.expander("Summary - per-fund reports (not built yet)"):
|
||||||
_comp = ", ".join(f"{c['sym']} {c['beta']:+.2f}"
|
st.info("Run `.venv/bin/python -m fundlab.reportdata` in the "
|
||||||
for c in _rec.get("components", [])[:4]) or \
|
"project root, then refresh.")
|
||||||
", ".join(f"{c['sym']} {c['beta']:+.2f}"
|
else:
|
||||||
for c in _d.get("components", [])[:4])
|
try:
|
||||||
_sum_rows.append({
|
_rd = json.loads(_RD.read_text())
|
||||||
"fund": _FL_LABELS.get(_s, _s),
|
_rfunds = _rd["funds"]
|
||||||
"verdict": _d.get("verdict", "n/a"),
|
except Exception as _e: # noqa: BLE001
|
||||||
"R² 5y": round(_rec["r2"], 3) if "r2" in _rec else None,
|
st.warning(f"report data unreadable: {_e}")
|
||||||
"alpha 5y": (f"{_rec['alpha_ann']*100:+.1f}% "
|
_rfunds = {}
|
||||||
f"(t={_rec['alpha_t']:+.1f})")
|
# on-demand reports: a symbol that stands ALONE in the Symbol box
|
||||||
if "alpha_ann" in _rec else None,
|
# (not a component of a comma-joined portfolio) gets a full
|
||||||
"components": _comp or "—",
|
# report, so any fund can be examined; results are cached on
|
||||||
})
|
# disk (reports/report_data_adhoc.json) so re-loading is instant
|
||||||
st.dataframe(pd.DataFrame(_sum_rows), width="stretch")
|
from fundlab import reportdata as _rdata
|
||||||
|
_standalone = [s for w in items if len(w) == 1 for s in w]
|
||||||
|
_new = [s for s in _standalone if s not in _rfunds]
|
||||||
|
if _new:
|
||||||
|
with st.spinner(
|
||||||
|
f"Building report(s) for {', '.join(s.upper() for s in _new)}"
|
||||||
|
" (first time for a fresh server: up to ~1 min for the "
|
||||||
|
"driver panel; cached afterwards)"):
|
||||||
|
_built = _rdata.ensure_adhoc(_new)
|
||||||
|
_rfunds = {**_built, **_rfunds} # ad-hoc entries first
|
||||||
|
for _i, (_s, _f) in enumerate(_built.items(), 1):
|
||||||
|
_f["meta"]["order"] = -_i # ad-hoc block sorts first
|
||||||
|
_rorder = sorted(_rfunds,
|
||||||
|
key=lambda s: _rfunds[s]["meta"]["order"])
|
||||||
|
if _rfunds:
|
||||||
|
st.subheader(f"Summary - per-fund reports "
|
||||||
|
f"({len(_rfunds)} funds)")
|
||||||
|
st.caption(
|
||||||
|
f"Generated {_rd['generated']}. Each fund: a narrative "
|
||||||
|
"discussion first (the performance, what drives it, and "
|
||||||
|
"what we do NOT know), then the equity curve, the period "
|
||||||
|
"table (fund vs fitted reference vs S&P 500, with the "
|
||||||
|
"fund-minus-reference gap), the return drivers, the "
|
||||||
|
"reference mix explained sleeve by sleeve, tax placement, "
|
||||||
|
"and the best peers from the same return-driver cluster. "
|
||||||
|
"All alphas are in excess of the 3-mo T-bill rate.")
|
||||||
|
_ag = []
|
||||||
|
for _s in _rorder:
|
||||||
|
_f = _rfunds[_s]
|
||||||
|
_m, _st = _f["meta"], _f.get("stats", {})
|
||||||
|
_ag.append({
|
||||||
|
"fund": (f"{_m['sym'].upper()}"
|
||||||
|
if _m["name"].upper() == _m["sym"].upper()
|
||||||
|
else f"{_m['sym'].upper()} — {_m['name'][:44]}"),
|
||||||
|
"group": _m["group"],
|
||||||
|
"5y": _st.get("t5y", "—"),
|
||||||
|
"CAGR": _st.get("cagr", "—"),
|
||||||
|
"maxDD": _st.get("mdd", "—"),
|
||||||
|
"R² 5y": _st.get("r2_5y", "—"),
|
||||||
|
"alpha 5y": _st.get("alpha_5y", "—"),
|
||||||
|
"cluster": (_f.get("peers") or {}).get("cluster", ""),
|
||||||
|
})
|
||||||
|
st.dataframe(pd.DataFrame(_ag), width="stretch",
|
||||||
|
hide_index=True)
|
||||||
|
for _s in _rorder:
|
||||||
|
render_fund_report(_rfunds[_s])
|
||||||
|
st.caption("← the rest of the Fund Lab continues below: "
|
||||||
|
"alpha search, return-driver clusters, N-PORT "
|
||||||
|
"cross-check, drawdown resilience, tax location, "
|
||||||
|
"and the CEF ranking.")
|
||||||
|
|
||||||
# --- alpha search: all screened funds (shortlist + longlist + harvest)
|
# --- alpha search: all screened funds (shortlist + longlist + harvest)
|
||||||
with st.expander("Alpha search — all screened funds, ranked"):
|
with st.expander("Alpha search — all screened funds, ranked"):
|
||||||
|
|
@ -660,6 +824,7 @@ with tab_fundlab:
|
||||||
else "—"),
|
else "—"),
|
||||||
"alpha 5y": (f"{_a5*100:+.1f}% (t={_v['alpha_t_5y']:+.1f})"
|
"alpha 5y": (f"{_a5*100:+.1f}% (t={_v['alpha_t_5y']:+.1f})"
|
||||||
if isinstance(_a5, (int, float)) else "—"),
|
if isinstance(_a5, (int, float)) else "—"),
|
||||||
|
"reference (5y)": _v.get("ref_5y") or "—",
|
||||||
"corr port": (f"{_v['corr_portfolio']:.2f}"
|
"corr port": (f"{_v['corr_portfolio']:.2f}"
|
||||||
if isinstance(_v.get("corr_portfolio"),
|
if isinstance(_v.get("corr_portfolio"),
|
||||||
(int, float)) else "—"),
|
(int, float)) else "—"),
|
||||||
|
|
@ -670,14 +835,18 @@ with tab_fundlab:
|
||||||
})
|
})
|
||||||
st.dataframe(pd.DataFrame(_tbl), width="stretch")
|
st.dataframe(pd.DataFrame(_tbl), width="stretch")
|
||||||
st.caption(
|
st.caption(
|
||||||
"Screen: daily total returns vs 21 broad sleeve axes (same "
|
"Screen: daily total returns IN EXCESS OF THE 3-MO T-BILL "
|
||||||
"set for every fund); 'alpha 5y' = OLS intercept over the "
|
"RATE (BIL) vs 21 broad sleeve axes (same set for every "
|
||||||
"last 5 years (t-stat); 'corr port' = correlation with your "
|
"fund); 'alpha 5y' = OLS intercept of the excess returns "
|
||||||
"current qspnx/pmaix portfolio; '6m + %' = share of rolling "
|
"over the last 5 years (t-stat) — i.e. outperformance vs "
|
||||||
"6-month windows where the fund beat its fitted sleeve mix. "
|
"the fund's OWN fitted sleeve mix (the 'reference' column), "
|
||||||
"CANDIDATE = R²5y < 0.6 (or < 0.85 with strong residual "
|
"not vs one index; a cash position earns exactly the t-bill "
|
||||||
"alpha), t5y ≥ 2, t-full ≥ 1.25, ≥ 45% positive windows, "
|
"rate and adds zero alpha. 'corr port' = correlation with "
|
||||||
"portfolio correlation < 0.3.")
|
"your current qspnx/pmaix portfolio; '6m + %' = share of "
|
||||||
|
"rolling 6-month windows where the fund beat its fitted "
|
||||||
|
"sleeve mix. CANDIDATE = R²5y < 0.6 (or < 0.85 with strong "
|
||||||
|
"residual alpha), t5y ≥ 2, t-full ≥ 1.25, ≥ 45% positive "
|
||||||
|
"windows, portfolio correlation < 0.3.")
|
||||||
|
|
||||||
# --- return-driver clusters: k-means on 35-sleeve loading vectors ---
|
# --- return-driver clusters: k-means on 35-sleeve loading vectors ---
|
||||||
with st.expander(
|
with st.expander(
|
||||||
|
|
@ -691,7 +860,11 @@ with tab_fundlab:
|
||||||
_syms, _V = _cl.loading_matrix()
|
_syms, _V = _cl.loading_matrix()
|
||||||
_fr = json.loads((_dc.RESULTS.parent /
|
_fr = json.loads((_dc.RESULTS.parent /
|
||||||
"factor_results.json").read_text())
|
"factor_results.json").read_text())
|
||||||
_lab = _cl.kmeans(_V, _ck)
|
# distance on the cash-emphasized matrix (a pure cash fund's
|
||||||
|
# level axis is otherwise swallowed by the low-exposure cloud);
|
||||||
|
# labels below use the raw _V values
|
||||||
|
_lab = _cl.kmeans(_cl.emphasized(_V, _fac.AXES.index("cash")),
|
||||||
|
_ck)
|
||||||
_sumrows = []
|
_sumrows = []
|
||||||
for c in range(_ck):
|
for c in range(_ck):
|
||||||
idx = [i for i, l in enumerate(_lab) if l == c]
|
idx = [i for i, l in enumerate(_lab) if l == c]
|
||||||
|
|
@ -699,7 +872,7 @@ with tab_fundlab:
|
||||||
continue
|
continue
|
||||||
med = _np.median(_V[idx], 0)
|
med = _np.median(_V[idx], 0)
|
||||||
top = _np.argsort(-_np.abs(med))[:4]
|
top = _np.argsort(-_np.abs(med))[:4]
|
||||||
prof = {_fac.DRIVERS[t]: float(med[t]) for t in top
|
prof = {_fac.AXES[t]: float(med[t]) for t in top
|
||||||
if abs(med[t]) >= 0.08}
|
if abs(med[t]) >= 0.08}
|
||||||
lab = _cl.label(prof)
|
lab = _cl.label(prof)
|
||||||
t5s = [_fr[_syms[i]].get("alpha_t_5y") for i in idx]
|
t5s = [_fr[_syms[i]].get("alpha_t_5y") for i in idx]
|
||||||
|
|
@ -736,7 +909,7 @@ with tab_fundlab:
|
||||||
continue
|
continue
|
||||||
med = _np.median(_V[idx], 0)
|
med = _np.median(_V[idx], 0)
|
||||||
top = _np.argsort(-_np.abs(med))[:4]
|
top = _np.argsort(-_np.abs(med))[:4]
|
||||||
prof = {_fac.DRIVERS[t]: float(med[t]) for t in top
|
prof = {_fac.AXES[t]: float(med[t]) for t in top
|
||||||
if abs(med[t]) >= 0.08}
|
if abs(med[t]) >= 0.08}
|
||||||
if _cl.label(prof) == _target:
|
if _cl.label(prof) == _target:
|
||||||
_members = [(i, idx[0]) for i in idx]
|
_members = [(i, idx[0]) for i in idx]
|
||||||
|
|
@ -767,11 +940,14 @@ with tab_fundlab:
|
||||||
r.pop("_t")
|
r.pop("_t")
|
||||||
st.dataframe(pd.DataFrame(_rows), width="stretch")
|
st.dataframe(pd.DataFrame(_rows), width="stretch")
|
||||||
st.caption(
|
st.caption(
|
||||||
"Each fund's daily returns are regressed on 35 sleeve axes "
|
"Each fund's daily total returns IN EXCESS OF THE 3-MO "
|
||||||
"(equity styles/sizes/intl/EM, the duration ladder, IG/HY/"
|
"T-BILL RATE (BIL) are regressed on 34 sleeve axes (equity "
|
||||||
"muni/MBS/preferred/EM-debt credit, sectors, gold/oil/"
|
"styles/sizes/intl/EM, the duration ladder, IG/HY/muni/MBS/"
|
||||||
"commodities, CTA); the 35-d loading vector is the fund's "
|
"preferred/EM-debt credit, sectors, gold/oil/commodities, "
|
||||||
"'return-driver signature' and k-means groups similar "
|
"CTA); the loading vector is the fund's 'return-driver "
|
||||||
|
"signature' — the betas are its NET INVESTED mix — plus a "
|
||||||
|
"virtual CASH axis = 1 − Σβ (net cash/T-bill position; 1 = "
|
||||||
|
"fully in cash, < 0 = levered). k-means groups similar "
|
||||||
"signatures. 'corr port' is shown for reference only - "
|
"signatures. 'corr port' is shown for reference only - "
|
||||||
"high-corr funds are REPLACEMENTS for current holdings, "
|
"high-corr funds are REPLACEMENTS for current holdings, "
|
||||||
"not rejections.")
|
"not rejections.")
|
||||||
|
|
@ -1092,9 +1268,10 @@ with tab_fundlab:
|
||||||
if _dr.get("note"):
|
if _dr.get("note"):
|
||||||
st.markdown("**Holdings cross-check:** " + _dr["note"])
|
st.markdown("**Holdings cross-check:** " + _dr["note"])
|
||||||
st.caption(
|
st.caption(
|
||||||
"Method: daily total returns; greedy forward selection on BIC "
|
"Method: daily total returns IN EXCESS OF THE 3-MO T-BILL RATE "
|
||||||
"(add only if ΔBIC ≥ 2 and |t| > 2); candidate sleeves curated per "
|
"(BIL); greedy forward selection on BIC (add only if ΔBIC ≥ 2 and "
|
||||||
"fund from the strategy text + N-PORT. β = exposure, not a literal "
|
"|t| > 2); candidate sleeves curated per fund from the strategy "
|
||||||
|
"text + N-PORT. β = exposure, not a literal "
|
||||||
"holding weight; 'drift' = mean |rolling 1y β − full β| relative to "
|
"holding weight; 'drift' = mean |rolling 1y β − full β| relative to "
|
||||||
"the full β. High-R² + low drift ≈ static mix; low R² with positive "
|
"the full β. High-R² + low drift ≈ static mix; low R² with positive "
|
||||||
"alpha ≈ market-neutral/alpha strategy.")
|
"alpha ≈ market-neutral/alpha strategy.")
|
||||||
|
|
|
||||||
148
data.py
148
data.py
|
|
@ -28,6 +28,56 @@ import pandas as pd
|
||||||
|
|
||||||
DEFAULT_ROOT = Path("~/prog/fin/stocks").expanduser()
|
DEFAULT_ROOT = Path("~/prog/fin/stocks").expanduser()
|
||||||
CACHE_DIR = Path(__file__).parent / ".cache"
|
CACHE_DIR = Path(__file__).parent / ".cache"
|
||||||
|
# Frozen overrides: stale (Yahoo-empty) tickers whose final series is
|
||||||
|
# snapshotted here by scripts/audit_stale.py. For symbols that have a
|
||||||
|
# frozen copy, the data-root files are ignored so a future goget
|
||||||
|
# re-download can never clobber the last known-good series.
|
||||||
|
FROZEN_DIR = Path(__file__).parent / "overrides" / "frozen"
|
||||||
|
# Corrections: per-symbol distribution fixes confirmed against official
|
||||||
|
# sources (see scripts/verify_official.py). Applied on top of whatever the
|
||||||
|
# data root / frozen dir says, so re-downloads can never clobber them.
|
||||||
|
# Format, one file per symbol in overrides/corrections/:
|
||||||
|
# {"dividends": {"remove": [["2008-12-18", 0.292], ...],
|
||||||
|
# "replace": {"2008-12-18": 0.0},
|
||||||
|
# "add": [["2007-12-18", 0.292], ...]},
|
||||||
|
# "capitalGains": {...same ops...},
|
||||||
|
# "as_of": "2026-08-31", "source": "<filing URL>", "note": "..."}
|
||||||
|
CORRECTIONS_DIR = Path(__file__).parent / "overrides" / "corrections"
|
||||||
|
_corr_cache: dict = {}
|
||||||
|
|
||||||
|
|
||||||
|
def _load_corrections(sym: str) -> dict:
|
||||||
|
f = CORRECTIONS_DIR / f"{sym.upper()}.json"
|
||||||
|
if f.exists():
|
||||||
|
try:
|
||||||
|
if f not in _corr_cache or _corr_cache[f][0] != f.stat().st_mtime_ns:
|
||||||
|
_corr_cache[f] = (f.stat().st_mtime_ns,
|
||||||
|
json.loads(f.read_text()))
|
||||||
|
return _corr_cache[f][1]
|
||||||
|
except Exception:
|
||||||
|
return {}
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
def _apply_corrections(sym: str, suffix: str, ser: pd.Series) -> pd.Series:
|
||||||
|
key = {"dividend": "dividends", "capitalGain": "capitalGains"}.get(suffix)
|
||||||
|
ops = _load_corrections(sym).get(key) if key else None
|
||||||
|
if not ops:
|
||||||
|
return ser
|
||||||
|
d = {ts: float(v) for ts, v in ser.items()}
|
||||||
|
for r in ops.get("remove", []):
|
||||||
|
ts = pd.Timestamp(r[0])
|
||||||
|
amt = r[1] if len(r) > 1 else None
|
||||||
|
if ts in d and (amt is None or abs(d[ts] - amt) < 1e-9):
|
||||||
|
del d[ts]
|
||||||
|
for ts_s, amt in ops.get("replace", {}).items():
|
||||||
|
d[pd.Timestamp(ts_s)] = float(amt)
|
||||||
|
for r in ops.get("add", []):
|
||||||
|
ts = pd.Timestamp(r[0])
|
||||||
|
d[ts] = d.get(ts, 0.0) + float(r[1])
|
||||||
|
if not d:
|
||||||
|
return pd.Series(dtype=float)
|
||||||
|
return pd.Series(d).sort_index()
|
||||||
|
|
||||||
_SUFFIXES = ("history", "dividend", "capitalGain")
|
_SUFFIXES = ("history", "dividend", "capitalGain")
|
||||||
_PANELS = ("adj", "close", "div", "capg")
|
_PANELS = ("adj", "close", "div", "capg")
|
||||||
|
|
@ -50,16 +100,37 @@ def _read_csv_clean(f: Path) -> pd.DataFrame:
|
||||||
return df
|
return df
|
||||||
|
|
||||||
|
|
||||||
|
def frozen_syms() -> set:
|
||||||
|
"""Symbols with a frozen history copy in the overrides dir."""
|
||||||
|
if not FROZEN_DIR.is_dir():
|
||||||
|
return set()
|
||||||
|
return {f.stem[: -len("-history")] for f in FROZEN_DIR.glob("*-history.csv")}
|
||||||
|
|
||||||
|
|
||||||
|
def _panel_paths(root: Path, suffix: str) -> list[tuple[str, Path]]:
|
||||||
|
"""(symbol, path) for every panel file; frozen copies shadow data-root."""
|
||||||
|
frozen = frozen_syms()
|
||||||
|
out = []
|
||||||
|
for f in sorted(root.glob(f"*-{suffix}.csv")):
|
||||||
|
sym = f.name[: -len(f"-{suffix}.csv")]
|
||||||
|
if sym in frozen:
|
||||||
|
continue
|
||||||
|
out.append((sym, f))
|
||||||
|
for f in sorted(FROZEN_DIR.glob(f"*-{suffix}.csv")) if FROZEN_DIR.is_dir() else []:
|
||||||
|
out.append((f.name[: -len(f"-{suffix}.csv")], f))
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
def _read_panel(root: Path, suffix: str, col: str) -> pd.DataFrame:
|
def _read_panel(root: Path, suffix: str, col: str) -> pd.DataFrame:
|
||||||
cols, syms = [], []
|
cols, syms = [], []
|
||||||
for f in sorted(root.glob(f"*-{suffix}.csv")):
|
for sym, f in _panel_paths(root, suffix):
|
||||||
try:
|
try:
|
||||||
df = _read_csv_clean(f)
|
df = _read_csv_clean(f)
|
||||||
except Exception:
|
except Exception:
|
||||||
continue
|
continue
|
||||||
if col in df.columns:
|
if col in df.columns:
|
||||||
cols.append(df[col])
|
cols.append(_apply_corrections(sym, suffix, df[col]))
|
||||||
syms.append(f.name[: -len(f"-{suffix}.csv")])
|
syms.append(sym)
|
||||||
if not cols:
|
if not cols:
|
||||||
return pd.DataFrame()
|
return pd.DataFrame()
|
||||||
out = pd.concat(cols, axis=1)
|
out = pd.concat(cols, axis=1)
|
||||||
|
|
@ -96,13 +167,26 @@ REFRESH_CADENCE = 30.0 # min seconds between actual cache rebuilds
|
||||||
_watchers: dict[tuple, threading.Thread] = {}
|
_watchers: dict[tuple, threading.Thread] = {}
|
||||||
_gen: dict[tuple, int] = {} # (root, cache) -> bundle generation counter
|
_gen: dict[tuple, int] = {} # (root, cache) -> bundle generation counter
|
||||||
def _scan_files(root: Path) -> dict:
|
def _scan_files(root: Path) -> dict:
|
||||||
"""{filename: (mtime_ns, size)} for every csv/json file in the data root."""
|
"""{filename: (mtime_ns, size)} for every csv/json file in the data root
|
||||||
|
plus the frozen overrides (namespaced under 'frozen/')."""
|
||||||
out = {}
|
out = {}
|
||||||
with os.scandir(root) as it:
|
with os.scandir(root) as it:
|
||||||
for e in it:
|
for e in it:
|
||||||
if e.is_file() and e.name.endswith((".csv", ".json")):
|
if e.is_file() and e.name.endswith((".csv", ".json")):
|
||||||
st = e.stat()
|
st = e.stat()
|
||||||
out[e.name] = (st.st_mtime_ns, st.st_size)
|
out[e.name] = (st.st_mtime_ns, st.st_size)
|
||||||
|
if FROZEN_DIR.is_dir():
|
||||||
|
with os.scandir(FROZEN_DIR) as it:
|
||||||
|
for e in it:
|
||||||
|
if e.is_file() and e.name.endswith((".csv", ".json")):
|
||||||
|
st = e.stat()
|
||||||
|
out["frozen/" + e.name] = (st.st_mtime_ns, st.st_size)
|
||||||
|
if CORRECTIONS_DIR.is_dir():
|
||||||
|
with os.scandir(CORRECTIONS_DIR) as it:
|
||||||
|
for e in it:
|
||||||
|
if e.is_file() and e.name.endswith(".json"):
|
||||||
|
st = e.stat()
|
||||||
|
out["corrections/" + e.name] = (st.st_mtime_ns, st.st_size)
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -154,14 +238,53 @@ def _apply_changes(root: Path, cache: Path, old: dict, new: dict) -> None:
|
||||||
return sfx, fname[: -len(f"-{sfx}.csv")]
|
return sfx, fname[: -len(f"-{sfx}.csv")]
|
||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
|
def _path(fname: str) -> Path:
|
||||||
|
# frozen/ namespaced files live in the overrides dir
|
||||||
|
return FROZEN_DIR / fname[8:] if fname.startswith("frozen/") else root / fname
|
||||||
|
|
||||||
updates: dict[str, dict] = {k: {} for k in _PANELS} # panel -> {sym: series}
|
updates: dict[str, dict] = {k: {} for k in _PANELS} # panel -> {sym: series}
|
||||||
drops: set[str] = set()
|
drops: set[str] = set()
|
||||||
|
# data-root files of frozen symbols are ignored: their canonical series
|
||||||
|
# lives in the overrides dir, which is tracked in the same scan
|
||||||
|
frozen = frozen_syms()
|
||||||
|
|
||||||
|
def _recompute_corrected(symfile: str) -> None:
|
||||||
|
"""corrections/{SYM}.json changed: re-derive the symbol's
|
||||||
|
dividend/capital-gain series from the base file + corrections."""
|
||||||
|
for sfx, colname, key in (("dividend", "Dividends", "div"),
|
||||||
|
("capitalGain", "Capital Gains", "capg")):
|
||||||
|
sym = None
|
||||||
|
p = None
|
||||||
|
for case in (symfile[:-5].lower(), symfile[:-5].upper()):
|
||||||
|
for base in (FROZEN_DIR, root):
|
||||||
|
q = base / f"{case}-{sfx}.csv"
|
||||||
|
if q.exists():
|
||||||
|
sym, p = case, q
|
||||||
|
break
|
||||||
|
if sym:
|
||||||
|
break
|
||||||
|
if p is None:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
df = _read_csv_clean(p)
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
if colname not in df.columns:
|
||||||
|
continue
|
||||||
|
updates[key][sym] = _apply_corrections(sym, sfx, df[colname]) \
|
||||||
|
.fillna(0.0)
|
||||||
|
|
||||||
for fname in changed:
|
for fname in changed:
|
||||||
|
if fname.startswith("corrections/"):
|
||||||
|
_recompute_corrected(fname[12:])
|
||||||
|
continue
|
||||||
sfx, sym = _suffix(fname)
|
sfx, sym = _suffix(fname)
|
||||||
if sfx is None:
|
if sfx is None:
|
||||||
continue
|
continue
|
||||||
|
if not fname.startswith("frozen/") and sym in frozen:
|
||||||
|
continue
|
||||||
try:
|
try:
|
||||||
df = _read_csv_clean(root / fname)
|
df = _read_csv_clean(_path(fname))
|
||||||
except Exception:
|
except Exception:
|
||||||
continue # e.g. a file mid-download
|
continue # e.g. a file mid-download
|
||||||
if sfx == "history":
|
if sfx == "history":
|
||||||
|
|
@ -170,11 +293,22 @@ def _apply_changes(root: Path, cache: Path, old: dict, new: dict) -> None:
|
||||||
if "Close" in df.columns:
|
if "Close" in df.columns:
|
||||||
updates["close"][sym] = df["Close"]
|
updates["close"][sym] = df["Close"]
|
||||||
elif sfx == "dividend" and "Dividends" in df.columns:
|
elif sfx == "dividend" and "Dividends" in df.columns:
|
||||||
updates["div"][sym] = df["Dividends"].fillna(0.0)
|
updates["div"][sym] = _apply_corrections(sym, sfx, df["Dividends"]) \
|
||||||
|
.fillna(0.0)
|
||||||
elif sfx == "capitalGain" and "Capital Gains" in df.columns:
|
elif sfx == "capitalGain" and "Capital Gains" in df.columns:
|
||||||
updates["capg"][sym] = df["Capital Gains"].fillna(0.0)
|
updates["capg"][sym] = _apply_corrections(sym, sfx, df["Capital Gains"]) \
|
||||||
|
.fillna(0.0)
|
||||||
for fname in removed:
|
for fname in removed:
|
||||||
sfx, sym = _suffix(fname)
|
sfx, sym = _suffix(fname)
|
||||||
|
if fname.startswith("corrections/"):
|
||||||
|
_recompute_corrected(fname[12:])
|
||||||
|
continue
|
||||||
|
if fname.startswith("frozen/"):
|
||||||
|
continue # frozen files are not data-root symbols
|
||||||
|
if sym in frozen:
|
||||||
|
continue # data-root file of a frozen symbol vanished; the
|
||||||
|
# frozen copy remains authoritative
|
||||||
|
sfx, sym = _suffix(fname)
|
||||||
if sfx is not None:
|
if sfx is not None:
|
||||||
drops.add(sym)
|
drops.add(sym)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -933,3 +933,253 @@ the overnight screen and had exited with it.
|
||||||
|
|
||||||
**App:** Fund Lab tab shows the CEF shortlist table (character
|
**App:** Fund Lab tab shows the CEF shortlist table (character
|
||||||
actual-vs-model flag, discount, 5y, vol, scenarios, tenders, score).
|
actual-vs-model flag, discount, 5y, vol, scenarios, tenders, score).
|
||||||
|
|
||||||
|
### CASH axis: money-market / cash-equivalent funds as a driver
|
||||||
|
|
||||||
|
**Problem:** money-market and ultra-short funds fell into the "no
|
||||||
|
dominant driver" cluster. There WAS a cash sleeve (shv; bil was dropped
|
||||||
|
from the regression for shv/bil collinearity), but cash funds still
|
||||||
|
didn't load on it: a fund's yield is a near-CONSTANT in return space,
|
||||||
|
so OLS puts it in the INTERCEPT (alpha_ann), not in any beta. shv/bil
|
||||||
|
betas only measure the response to rate CHANGES — tiny for cash-like
|
||||||
|
funds. Evidence: qcmmrx (Money Market Account) had shv 0.13, bil 0.12,
|
||||||
|
R² 0.08, but alpha_ann 1.91%/yr = the average cash level over its
|
||||||
|
history.
|
||||||
|
|
||||||
|
**Benchmark:** the canonical cash benchmark is the 13-week T-bill /
|
||||||
|
0-3m Treasury index (SIXM). Local stand-ins: shv/sgov/bil/gbil
|
||||||
|
total-return (Adj Close), trailing 1y ≈ 3.7% in the current regime.
|
||||||
|
|
||||||
|
**Fix (factors.py + cluster.py + app.py):**
|
||||||
|
- `factors.cash_yield()`: shv trailing-1y total return (fallback sgov,
|
||||||
|
bil) — the normalizer.
|
||||||
|
- `factors.AXES = DRIVERS + ["cash"]`: a VIRTUAL cash axis per fund =
|
||||||
|
alpha_ann / cash_yield (1.0 = "earns the cash rate"), from the full
|
||||||
|
window (rec5 fallback when the row falls back to rec5). It is a
|
||||||
|
clustering/display axis, NOT a regressor (the level is already in
|
||||||
|
the intercept; regressing on a constant is collinear by design).
|
||||||
|
- `cluster.loading_matrix()` appends the cash column (winsorized ±4
|
||||||
|
like the betas). SLEEVE_NAME["cash"] = "cash (yield)".
|
||||||
|
- `cluster.emphasized(V)`: the cash axis is a LEVEL, not a sensitivity
|
||||||
|
— in raw Euclidean space a pure cash fund (0,...,0,~0.5) sits inside
|
||||||
|
the low-exposure balanced/target-date cloud and k-means swallows it.
|
||||||
|
K-means (app + run_kmeans) runs on the cash-2x-emphasized matrix;
|
||||||
|
LABELS still use the raw values. The hclust tree stays raw.
|
||||||
|
- `cluster.label()`: cash-aware — the median cash in a mixed
|
||||||
|
low-exposure cluster is diluted, so cash counts as the driver at
|
||||||
|
>=0.25 (vs 0.30 for betas) and must be >=1.5x the runner-up.
|
||||||
|
|
||||||
|
**Result (k=30):** the grab-bag 331-fund "no dominant driver" cluster
|
||||||
|
splits into "cash (yield) +0.64" (n=187: qcmmrx + the ultra-short
|
||||||
|
government/bond funds), "cash (yield) +1.26" (n=59 pure), and the
|
||||||
|
genuinely balanced remainder. 637 funds now have CASH as their
|
||||||
|
dominant axis (>=0.30 and > every beta) — mostly the short-duration
|
||||||
|
complex, which is correct: their return IS mostly the coupon level.
|
||||||
|
|
||||||
|
**Note:** the machine rebooted during this work (12:50) — it silently
|
||||||
|
kills nohup'd processes (the CEF batch and the first watchdog both
|
||||||
|
died that way; the batch was resumable so no data was lost).
|
||||||
|
server_watchdog.sh had to be relaunched manually; consider a
|
||||||
|
boot-time starter (systemd/cron @reboot) if reboots repeat.
|
||||||
|
- 2026-08-30 15:09 === stage screen ===
|
||||||
|
- 2026-08-30 15:09 screen: 2384 funds, 2384 to do
|
||||||
|
- 2026-08-30 15:10 screen: 100/2384
|
||||||
|
- 2026-08-30 15:11 screen: 200/2384
|
||||||
|
- 2026-08-30 15:11 screen: 300/2384
|
||||||
|
- 2026-08-30 15:12 screen: 400/2384
|
||||||
|
- 2026-08-30 15:12 screen: 500/2384
|
||||||
|
- 2026-08-30 15:13 screen: 600/2384
|
||||||
|
- 2026-08-30 15:13 screen: 700/2384
|
||||||
|
- 2026-08-30 15:14 screen: 800/2384
|
||||||
|
- 2026-08-30 15:14 screen: 900/2384
|
||||||
|
- 2026-08-30 15:15 screen: 1000/2384
|
||||||
|
- 2026-08-30 15:15 screen: 1100/2384
|
||||||
|
- 2026-08-30 15:16 screen: 1200/2384
|
||||||
|
- 2026-08-30 15:17 screen: 1300/2384
|
||||||
|
- 2026-08-30 15:17 screen: 1400/2384
|
||||||
|
- 2026-08-30 15:18 screen: 1500/2384
|
||||||
|
- 2026-08-30 15:18 screen: 1600/2384
|
||||||
|
- 2026-08-30 15:19 screen: 1700/2384
|
||||||
|
- 2026-08-30 15:19 screen: 1800/2384
|
||||||
|
- 2026-08-30 15:20 screen: 1900/2384
|
||||||
|
- 2026-08-30 15:20 screen: 2000/2384
|
||||||
|
- 2026-08-30 15:21 screen: 2100/2384
|
||||||
|
- 2026-08-30 15:21 screen: 2200/2384
|
||||||
|
- 2026-08-30 15:22 screen: 2300/2384
|
||||||
|
- 2026-08-30 15:22 screen done: 2384 funds
|
||||||
|
- 2026-08-30 15:22 === stage finalize ===
|
||||||
|
- 2026-08-30 15:22 finalize: 2384 funds screened
|
||||||
|
- 2026-08-30 15:22 1339 sleeve mix
|
||||||
|
- 2026-08-30 15:22 1001 weak/unstable alpha
|
||||||
|
- 2026-08-30 15:22 17 no 5y window
|
||||||
|
- 2026-08-30 15:22 11 CANDIDATE
|
||||||
|
- 2026-08-30 15:22 10 alpha, but correlated with current portfolio
|
||||||
|
- 2026-08-30 15:22 6 alpha in 5y window, but not persistent
|
||||||
|
- 2026-08-30 15:22 candidates v1 name-filter would have missed: ['aguax', 'etsix', 'femdx', 'hicox', 'prfrx', 'puls', 'rctix', 'rpifx', 'scfzx']
|
||||||
|
- 2026-08-30 15:22 === overnight run finished in 0.2h ===
|
||||||
|
|
||||||
|
### Alphas recomputed in EXCESS of the 3-mo T-bill rate (risk-free netting)
|
||||||
|
|
||||||
|
**Question that triggered it:** "Are we using cash return as a risk-free
|
||||||
|
rate in the alpha calculations?" — No. Alpha was the OLS intercept of
|
||||||
|
RAW daily total returns. For a fund whose net sleeve exposure is not
|
||||||
|
~100% (under-invested or levered), the raw intercept absorbs the T-bill
|
||||||
|
yield on the uninvested/levered part, so "alpha" mixed skill with cash
|
||||||
|
drag. Magnitude (5y, R²>0.5 funds): 582 funds >2%/yr apart, 533 in
|
||||||
|
1-2%, 345 in 0.5-1%. Sum-of-betas was also polluted by level-matching
|
||||||
|
(median 1.15; a plain growth fund like bggsx showed 3.7 with a −10%/yr
|
||||||
|
"alpha" that was pure level-splitting).
|
||||||
|
|
||||||
|
**Changes:**
|
||||||
|
- decompose.py: `rf_series()` = BIL (SPDR 1-3mo T-Bill) daily total
|
||||||
|
return — the local stand-in for the 3-mo T-bill yield; `excess()`
|
||||||
|
nets the fund AND the sleeves against it before every regression.
|
||||||
|
Cash positions now contribute exactly zero (cash IS the rf).
|
||||||
|
- CASH_SLEEVES {shv, bil} dropped from the regressors: in excess space
|
||||||
|
they are ~0 columns (ill-conditioning); the cash position is captured
|
||||||
|
by the residual instead. Same for factors.py (shv added to
|
||||||
|
DROP_FROM_REGRESSION).
|
||||||
|
- **FULL_WINDOW moved 1990-01-01 → 2007-06-01** (BIL inception):
|
||||||
|
mixing raw pre-2007 with excess post-2007 returns breaks the
|
||||||
|
full-window fit (cosix: R²≈0, zero components selected).
|
||||||
|
- **CASH axis redefined** from alpha_ann/cash_yield (the old version
|
||||||
|
was measuring the yield level that no longer lives in the intercept)
|
||||||
|
to **net cash position = 1 − Σβ**: the betas are the net-invested
|
||||||
|
mix, the leftover is cash/T-bills. Pure MMF → 1.0; levered → < 0.
|
||||||
|
Labeled "cash (net posn)". `factors.cash_yield()` removed.
|
||||||
|
- Alphas in the app are now true excess-return alphas: intercept of
|
||||||
|
(fund − rf) on (sleeves − rf).
|
||||||
|
|
||||||
|
**Verification (probes):** qcmmrx (money market): alpha −0.17%/yr
|
||||||
|
(t=−1.3, noise), cash 1.00. vsbsx (short-T index): alpha 0.03%, cash
|
||||||
|
0.77 + short duration. bggsx: Σβ 1.25 (was 3.7), alpha −3.6%
|
||||||
|
(t=−0.6). IVV: alpha 0.00% (t=+36.7). cosix full-window fixed
|
||||||
|
(R² 0.60, vweax 0.45/agg 0.15/ief 0.15).
|
||||||
|
|
||||||
|
**Consequence — the CANDIDATE list shrank 250 → 11.** Most of the old
|
||||||
|
250 were under-invested funds (bond funds with Σβ<1) whose "alpha" was
|
||||||
|
the T-bill yield on their uninvested portion. The 11 that survive are
|
||||||
|
funds whose excess alpha is real. Verdict mix now: 1339 sleeve mix,
|
||||||
|
1001 weak/unstable alpha, 11 CANDIDATE, 10 correlated, 6 not
|
||||||
|
persistent, 17 no 5y window.
|
||||||
|
|
||||||
|
**Reference visibility (the "what is alpha computed vs" question):**
|
||||||
|
alpha is NOT vs one index — it is vs the fund's own fitted sleeve mix
|
||||||
|
(BIC forward selection). fundlab/refback.py recomputes the forward
|
||||||
|
selection per fund and stores `ref_5y`/`ref_full` strings in
|
||||||
|
search_all.json; the app's alpha-search table now has a "reference
|
||||||
|
(5y)" column.
|
||||||
|
|
||||||
|
**Backups of the raw-alpha era (NOT deleted):**
|
||||||
|
factor_results_rawalpha.json, decompose_results_rawalpha.json,
|
||||||
|
search_all_rawalpha.json, cluster_kmeans_rawalpha.json.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Per-fund report: HTML + app + narrative engine (2026-08-30)
|
||||||
|
|
||||||
|
**Deliverable.** `fundlab/report.py` -> `reports/fund_report.html`
|
||||||
|
(self-contained, plotly inlined, 20 MB) and `fundlab/reportdata.py` ->
|
||||||
|
`reports/report_data.json` (3 MB, the app's static build). 24 funds: the
|
||||||
|
11 excess-return candidates + the 13 unique shortlist funds (pmfkx/lcrix/
|
||||||
|
egrsx are share classes of pmaix/lcorx/eagmx and are merged).
|
||||||
|
|
||||||
|
Per fund: max-history equity curve (fund vs fitted reference vs IVV);
|
||||||
|
period table (full/5y/1y, the 5 market episodes, 6 calendar years) with
|
||||||
|
the **fund-minus-reference** column (period alpha/timing); drivers
|
||||||
|
(reference-model R²/alpha/t + 34-sleeve signature + curated decomposition
|
||||||
|
verdict + N-PORT cross-check notes); the reference mix explained
|
||||||
|
sleeve-by-sleeve (SLEEVE_DESC: what each exposure actually is); tax
|
||||||
|
character + placement; and a peer table of the 4 best-alpha funds in the
|
||||||
|
same k=30 return-driver cluster with computed adv/dis.
|
||||||
|
|
||||||
|
**BUG FOUND AND FIXED — `mix_series()` never applied the betas.** The
|
||||||
|
"fitted reference" curve summed the RAW sleeve daily returns instead of
|
||||||
|
β·return. For high-fit funds the reference was garbage (JLPSX "reference"
|
||||||
|
+407% 5y vs the fund's +123%; CVSIX +465%; PMAIX +1160%). After the fix
|
||||||
|
the mix tracks the fund (JLPSX ref +127% vs fund +123%). Every reference
|
||||||
|
curve and table in the HTML report was wrong before this and has been
|
||||||
|
regenerated. Lesson: a regression on returns does not hand you a price
|
||||||
|
path — the β weighting is the whole point.
|
||||||
|
|
||||||
|
**Weak-fit funds anchor to CASH, not their fitted mix.** For idiosyncratic
|
||||||
|
funds (R² < 0.5) the BIC forward selection can pick a statistically-thin
|
||||||
|
OFFSETTING combination (SCFZX: +0.35 VIX futures, −0.23 20+y Treasuries,
|
||||||
|
+0.10 HY) whose cumulated path is meaningless (a "reference" that loses
|
||||||
|
79% in 2022 for a fund that lost 2.4%). Below the 0.5 fit gate the
|
||||||
|
performance table and curve use BIL as the reference; the loadings are
|
||||||
|
still shown with an explicit "weak fit — read with care" caveat.
|
||||||
|
|
||||||
|
**Narrative engine (`fundlab/narrative.py`).** Data-driven English prose,
|
||||||
|
5 paragraphs per fund: (1) what the fund is (objective, N-PORT buckets,
|
||||||
|
cluster); (2) the performance in plain terms (CAGR/vol/DD, 5y vs reference,
|
||||||
|
episode behaviour, calendar-year pattern); (3) what is driving it — tiered
|
||||||
|
by fit (≥0.7 "mostly the exposures", 0.5–0.7 "mix + residual", <0.5
|
||||||
|
"idiosyncratic: here is the estimate and its t-stat"); (4) **what we do
|
||||||
|
NOT know** — stated explicitly: the unexplained share, alpha steadiness
|
||||||
|
(share of 6m windows trailing), recent-vs-full significance, short sample,
|
||||||
|
holdings opacity (egrix: 100% in one managed fund, underlying undisclosed);
|
||||||
|
(5) bottom line (account placement, best cluster peer, portfolio
|
||||||
|
correlation). Rules learned while reviewing the prose: negative/weak 5y
|
||||||
|
alpha must not be called "outperformance" (the template assumed positive
|
||||||
|
alpha and lied about atesx, −1.6% t=−0.5); MIXED tax placement must not be
|
||||||
|
rendered as "IRA"; a fund with no price history must not be assigned a
|
||||||
|
cluster (zero loading vector parks everything in the cash cluster);
|
||||||
|
drift < 0.5 = "roughly stable" (0.44 is not "tactical"); sleeve prose
|
||||||
|
needs short names (dbb/gsg → "broad commodities") because SLEEVE_DESC
|
||||||
|
lead-ins reference sibling tickers.
|
||||||
|
|
||||||
|
**App integration.** The Fund Lab "Summary" page now renders
|
||||||
|
`reports/report_data.json`: at-a-glance table (24 funds: 5y, CAGR, maxDD,
|
||||||
|
R²5y, alpha5y, cluster) + one expander per fund (narrative first, then
|
||||||
|
chart, period table, drivers, reference mix, tax, peers) + an "expand
|
||||||
|
all" checkbox. Static build so the page stays fast; regenerate with
|
||||||
|
`python -m fundlab.reportdata` (~8 s) and `python -m fundlab.report`
|
||||||
|
(~11 s for the HTML).
|
||||||
|
|
||||||
|
**Report charts: re-basing-on-zoom widget (2nd pass).** The first report
|
||||||
|
build used static st.plotly_chart with pre-rebased series — zooming to a
|
||||||
|
window left the lines starting at different levels (no comparison
|
||||||
|
possible). Replaced with the SAME widget as the Equity curves tab
|
||||||
|
(`chart_widget.equity_chart_html` + st.iframe): on every relayout each
|
||||||
|
visible line is re-based to 1.0 at its left edge and y fits the visible
|
||||||
|
data, so fund/reference/index are comparable in any window. report_data
|
||||||
|
still stores the full-history series; the app divides by each series'
|
||||||
|
first point before handing it to the widget (per-series 1.0 start, as
|
||||||
|
the widget expects). Also removed the "expand all" checkbox (24 expanded
|
||||||
|
sections made the page unusable and hid the sections below) and added a
|
||||||
|
"rest of the Fund Lab continues below" marker.
|
||||||
|
|
||||||
|
**On-demand reports for any Symbol-box fund.** `reportdata.ensure_adhoc(syms)`
|
||||||
|
builds the same full report entry (narrative, chart, period table, drivers,
|
||||||
|
reference, tax, peers) for ARBITRARY symbols, cached in memory + on disk
|
||||||
|
(reports/report_data_adhoc.json, gitignored) so repeat loads are instant and
|
||||||
|
survive restarts; build time ~0.3-0.9 s per new fund after the one-time
|
||||||
|
~30-60 s driver-panel warmup. The app triggers it for symbols that stand
|
||||||
|
ALONE in the Symbol box (a parsed item with a single component) - portfolio
|
||||||
|
components (comma-joined) are explicitly excluded, per user request. Ad-hoc
|
||||||
|
entries render at the top of the Fund Lab Summary as group "A" (before the
|
||||||
|
pre-built 24), the per-fund rendering was extracted into render_fund_report()
|
||||||
|
shared by both, and a pointer at the top of the page tells the user where
|
||||||
|
the generated reports are. ETFs with no name on file render as "A01 · TLT"
|
||||||
|
(no duplicated name).
|
||||||
|
|
||||||
|
**Style-tilt battery in the report pipeline (2026-08-30, 3rd pass).**
|
||||||
|
`fundlab/styletilt.py`: 22 style/asset sleeves (EFA/VWO, growth/value,
|
||||||
|
IWM/RSP size+equal-weight, USMV/DFLVX low-vol, QUAL, MTUM, HDV/VYM
|
||||||
|
dividend, TLT, GLD, FXE/FXY/FXU, the five big sectors) regressed on the
|
||||||
|
fund's excess-of-T-bill returns, full history + 5y. Plain OLS gives every
|
||||||
|
factor's β + t (exploratory); BIC forward selection gives the IDENTIFIED
|
||||||
|
tilt stack (strict gate); residual alpha after the identified stack says
|
||||||
|
"skill left or pure factor exposure". Data-driven commentary: tilt
|
||||||
|
sentences with strength words (t≥10 strong / ≥5 clear / ≥2 modest),
|
||||||
|
sign-specific phrasing for the tricky ones (short-euro = USD carry,
|
||||||
|
anti-quality = flip side of high payout, anti-momentum = contrarian),
|
||||||
|
5y-only factors called out separately, and an explicit residual-verdict
|
||||||
|
paragraph. Wired as a "Style tilts" block (factor table + commentary)
|
||||||
|
into both report builders (app + HTML); ~0.1-0.8 s per fund after the
|
||||||
|
one-time battery-panel build. All 24 pre-built + 8 ad-hoc reports
|
||||||
|
rebuilt (23/24 have the block; lcorx has no history). Worked example
|
||||||
|
(lvhi): identified stack = intl-dev 0.78 + short EUR 0.42 + HDV +0.28
|
||||||
|
(t+20) + anti-QUAL 0.21 (t-12) + short FXY + short VWO; residual alpha
|
||||||
|
+2.3%/y t=+1.1 -> "factor exposure, not skill".
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ HERE = Path(__file__).parent
|
||||||
RESULTS = HERE / "factor_results.json"
|
RESULTS = HERE / "factor_results.json"
|
||||||
TREE = HERE / "cluster_tree.json"
|
TREE = HERE / "cluster_tree.json"
|
||||||
KMEANS = HERE / "cluster_kmeans.json"
|
KMEANS = HERE / "cluster_kmeans.json"
|
||||||
from fundlab.factors import DRIVERS # noqa: E402
|
from fundlab.factors import AXES, DRIVERS # noqa: E402
|
||||||
|
|
||||||
|
|
||||||
def log(msg: str) -> None:
|
def log(msg: str) -> None:
|
||||||
|
|
@ -50,6 +50,11 @@ def loading_matrix() -> tuple[list[str], np.ndarray]:
|
||||||
continue
|
continue
|
||||||
row = np.array([f["betas"].get(s, 0.0) or 0.0 for s in DRIVERS],
|
row = np.array([f["betas"].get(s, 0.0) or 0.0 for s in DRIVERS],
|
||||||
dtype=float)
|
dtype=float)
|
||||||
|
# virtual CASH axis = net cash position = 1 - sum of the betas.
|
||||||
|
# Alphas are in excess of the T-bill rate, so the betas are the
|
||||||
|
# NET INVESTED mix; whatever is left over sits in cash/T-bills.
|
||||||
|
# Pure money-market fund: all betas ~ 0 -> cash ~ 1.
|
||||||
|
row = np.append(row, 1.0 - row.sum())
|
||||||
# winsorize at +/-4: everything beyond that is an OLS noise fit
|
# winsorize at +/-4: everything beyond that is an OLS noise fit
|
||||||
# (R2 ~ 0.01, |t| < 2 - e.g. fyhtx shv +63.8), never a real
|
# (R2 ~ 0.01, |t| < 2 - e.g. fyhtx shv +63.8), never a real
|
||||||
# exposure (no open-end fund runs 400% of a sleeve)
|
# exposure (no open-end fund runs 400% of a sleeve)
|
||||||
|
|
@ -120,7 +125,7 @@ def cluster_means(syms: list[str], V: np.ndarray,
|
||||||
idx = [i for i, s in assign.items() if s == c]
|
idx = [i for i, s in assign.items() if s == c]
|
||||||
med = np.median(V[idx], axis=0)
|
med = np.median(V[idx], axis=0)
|
||||||
top = np.argsort(-np.abs(med))[:4]
|
top = np.argsort(-np.abs(med))[:4]
|
||||||
prof = {DRIVERS[t]: float(med[t]) for t in top
|
prof = {AXES[t]: float(med[t]) for t in top
|
||||||
if abs(med[t]) >= 0.05}
|
if abs(med[t]) >= 0.05}
|
||||||
out.append({"n": len(idx), "top": prof,
|
out.append({"n": len(idx), "top": prof,
|
||||||
"syms": [syms[i] for i in idx]})
|
"syms": [syms[i] for i in idx]})
|
||||||
|
|
@ -140,15 +145,41 @@ SLEEVE_NAME = {
|
||||||
"xlv": "healthcare", "xlp": "staples", "xlu": "utilities",
|
"xlv": "healthcare", "xlp": "staples", "xlu": "utilities",
|
||||||
"xly": "consumer disc", "xlb": "materials", "dbmf": "CTA/futures",
|
"xly": "consumer disc", "xlb": "materials", "dbmf": "CTA/futures",
|
||||||
"dbb": "commodities",
|
"dbb": "commodities",
|
||||||
|
"cash": "cash (net posn)",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# the CASH axis is a POSITION (net cash, 1.0 = fully in cash), not a
|
||||||
|
# return SENSITIVITY like the betas. In raw Euclidean space a
|
||||||
|
# pure cash fund (0,...,0,~0.5) sits inside the cloud of low-exposure
|
||||||
|
# balanced/target-date funds and k-means swallows it. Emphasize the axis
|
||||||
|
# for DISTANCE only (labels still use the raw values).
|
||||||
|
CASH_EMPHASIS = 2.0
|
||||||
|
|
||||||
|
|
||||||
|
def emphasized(V: np.ndarray, ci: int) -> np.ndarray:
|
||||||
|
W = V.copy()
|
||||||
|
W[:, ci] *= CASH_EMPHASIS
|
||||||
|
return W
|
||||||
|
|
||||||
|
|
||||||
def label(prof: dict) -> str:
|
def label(prof: dict) -> str:
|
||||||
# a real driver shows up as >=0.3 on a median loading; below that the
|
# a real driver shows up as >=0.3 on a median loading; below that the
|
||||||
# cluster is balanced mixes with no single dominant driver
|
# cluster is balanced mixes with no single dominant driver. The CASH
|
||||||
if not prof or max(abs(v) for v in prof.values()) < 0.30:
|
# axis is a level, not a beta: in a mixed low-exposure cluster the
|
||||||
|
# median cash is diluted, so it gets a slightly lower threshold and
|
||||||
|
# must clearly beat the runner-up to count as THE driver.
|
||||||
|
if not prof:
|
||||||
return "no dominant driver (balanced/idio)"
|
return "no dominant driver (balanced/idio)"
|
||||||
names = sorted(prof, key=lambda s: -abs(prof[s]))
|
names = sorted(prof, key=lambda s: -abs(prof[s]))
|
||||||
|
top_s, top_v = names[0], prof[names[0]]
|
||||||
|
runner = abs(prof[names[1]]) if len(names) > 1 else 0.0
|
||||||
|
if top_s == "cash":
|
||||||
|
if top_v >= 0.25 and top_v >= 1.5 * runner:
|
||||||
|
return " + ".join(f"{SLEEVE_NAME.get(s, s)} {prof[s]:+.2f}"
|
||||||
|
for s in names[:3])
|
||||||
|
return "no dominant driver (balanced/idio)"
|
||||||
|
if abs(top_v) < 0.30:
|
||||||
|
return "no dominant driver (balanced/idio)"
|
||||||
return " + ".join(f"{SLEEVE_NAME.get(s, s)} {prof[s]:+.2f}"
|
return " + ".join(f"{SLEEVE_NAME.get(s, s)} {prof[s]:+.2f}"
|
||||||
for s in names[:3])
|
for s in names[:3])
|
||||||
|
|
||||||
|
|
@ -182,7 +213,7 @@ def kmeans(V: np.ndarray, k: int, seed: int = 0,
|
||||||
|
|
||||||
def run_kmeans(k: int = 30) -> dict:
|
def run_kmeans(k: int = 30) -> dict:
|
||||||
syms, V = loading_matrix()
|
syms, V = loading_matrix()
|
||||||
lab = kmeans(V, k)
|
lab = kmeans(emphasized(V, AXES.index("cash")), k)
|
||||||
out: dict[int, dict] = {}
|
out: dict[int, dict] = {}
|
||||||
for c in range(k):
|
for c in range(k):
|
||||||
idx = [i for i, l in enumerate(lab) if l == c]
|
idx = [i for i, l in enumerate(lab) if l == c]
|
||||||
|
|
@ -190,7 +221,7 @@ def run_kmeans(k: int = 30) -> dict:
|
||||||
continue
|
continue
|
||||||
med = np.median(V[idx], axis=0)
|
med = np.median(V[idx], axis=0)
|
||||||
top = np.argsort(-np.abs(med))[:4]
|
top = np.argsort(-np.abs(med))[:4]
|
||||||
prof = {DRIVERS[t]: float(med[t]) for t in top
|
prof = {AXES[t]: float(med[t]) for t in top
|
||||||
if abs(med[t]) >= 0.08}
|
if abs(med[t]) >= 0.08}
|
||||||
out[c] = {"n": len(idx), "top": prof, "label": label(prof),
|
out[c] = {"n": len(idx), "top": prof, "label": label(prof),
|
||||||
"syms": [syms[i] for i in idx]}
|
"syms": [syms[i] for i in idx]}
|
||||||
|
|
@ -203,7 +234,7 @@ def run() -> None:
|
||||||
log(f"cluster: {len(syms)} funds x {V.shape[1]} drivers")
|
log(f"cluster: {len(syms)} funds x {V.shape[1]} drivers")
|
||||||
merges = hclust(V)
|
merges = hclust(V)
|
||||||
TREE.write_text(json.dumps({"syms": syms, "merges": merges,
|
TREE.write_text(json.dumps({"syms": syms, "merges": merges,
|
||||||
"n": len(syms), "sleeves": DRIVERS}))
|
"n": len(syms), "sleeves": AXES}))
|
||||||
log(f"hierarchical tree written in {time.time() - t0:.0f}s -> {TREE.name}")
|
log(f"hierarchical tree written in {time.time() - t0:.0f}s -> {TREE.name}")
|
||||||
# NOTE: fixed-k cuts of the tree peel small pure-sleeve clusters off a
|
# NOTE: fixed-k cuts of the tree peel small pure-sleeve clusters off a
|
||||||
# giant blend blob (most funds are multi-sleeve mixes) - the useful
|
# giant blend blob (most funds are multi-sleeve mixes) - the useful
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
1
fundlab/cluster_kmeans_rawalpha.json
Normal file
1
fundlab/cluster_kmeans_rawalpha.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -22,6 +22,7 @@ intercept; alphas are annualized (x252); t-stats use the OLS covariance.
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
from functools import lru_cache
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
@ -49,6 +50,29 @@ def adj_close(sym: str, root: Path = DATA) -> pd.Series | None:
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache(maxsize=1)
|
||||||
|
def rf_series() -> pd.Series | None:
|
||||||
|
"""Daily risk-free rate: BIL (SPDR 1-3 Month T-Bill) total return —
|
||||||
|
the local stand-in for the 3-month T-bill yield. Alphas are computed
|
||||||
|
in EXCESS of this rate (both the fund and the sleeves are netted
|
||||||
|
against it), so the intercept is a true excess-return alpha and a
|
||||||
|
cash position contributes zero (cash IS the risk-free rate). 0 where
|
||||||
|
BIL has no history (pre-2007)."""
|
||||||
|
a = adj_close("bil")
|
||||||
|
if a is None:
|
||||||
|
return None
|
||||||
|
return a.pct_change().fillna(0.0)
|
||||||
|
|
||||||
|
|
||||||
|
def excess(panel: pd.DataFrame) -> pd.DataFrame:
|
||||||
|
"""Net every column against the daily risk-free rate."""
|
||||||
|
rf = rf_series()
|
||||||
|
if rf is None:
|
||||||
|
return panel
|
||||||
|
rf = rf.reindex(panel.index).fillna(0.0)
|
||||||
|
return panel.sub(rf, axis=0)
|
||||||
|
|
||||||
|
|
||||||
def returns_panel(symbols: list[str], start: str | None = None) -> pd.DataFrame:
|
def returns_panel(symbols: list[str], start: str | None = None) -> pd.DataFrame:
|
||||||
"""Daily simple returns, outer-joined on dates (NaN where a series
|
"""Daily simple returns, outer-joined on dates (NaN where a series
|
||||||
has no data). Callers must handle missing values per regressor —
|
has no data). Callers must handle missing values per regressor —
|
||||||
|
|
@ -207,9 +231,17 @@ CANDIDATES: dict[str, list[str]] = {
|
||||||
}
|
}
|
||||||
# share classes: same underlying fund
|
# share classes: same underlying fund
|
||||||
ALIAS = {"pmfkx": "pmaix", "lcrix": "lcorx", "egrsx": "eagmx"}
|
ALIAS = {"pmfkx": "pmaix", "lcrix": "lcorx", "egrsx": "eagmx"}
|
||||||
FULL_WINDOW = "1990-01-01" # effectively all history
|
FULL_WINDOW = "2007-06-01" # from BIL inception: alphas are in excess of
|
||||||
|
# the T-bill rate, which needs the rf series (raw pre-2007 returns
|
||||||
|
# mixed with excess post-2007 returns breaks the full-window fit)
|
||||||
RECENT_WINDOW = "2021-01-01" # last ~5 years
|
RECENT_WINDOW = "2021-01-01" # last ~5 years
|
||||||
|
|
||||||
|
# sleeves that ARE the risk-free rate. Alphas are now computed in excess of
|
||||||
|
# the T-bill rate, so these columns are ~0 in excess space and would make
|
||||||
|
# the regression ill-conditioned. Cash exposure is captured by the residual
|
||||||
|
# (1 - sum of betas) instead, so they are dropped from the regressors.
|
||||||
|
CASH_SLEEVES = {"shv", "bil"}
|
||||||
|
|
||||||
|
|
||||||
def _drift(rb: pd.DataFrame, full_beta: np.ndarray) -> dict[str, float]:
|
def _drift(rb: pd.DataFrame, full_beta: np.ndarray) -> dict[str, float]:
|
||||||
"""Mean |rolling beta - full-sample beta| per component, as a fraction
|
"""Mean |rolling beta - full-sample beta| per component, as a fraction
|
||||||
|
|
@ -225,13 +257,14 @@ def _drift(rb: pd.DataFrame, full_beta: np.ndarray) -> dict[str, float]:
|
||||||
def decompose(fund: str, start: str = FULL_WINDOW,
|
def decompose(fund: str, start: str = FULL_WINDOW,
|
||||||
candidates: dict[str, list[str]] | None = None) -> dict:
|
candidates: dict[str, list[str]] | None = None) -> dict:
|
||||||
cand_syms = (candidates or CANDIDATES).get(fund, [])
|
cand_syms = (candidates or CANDIDATES).get(fund, [])
|
||||||
r = returns_panel([fund] + cand_syms, start=start)
|
r = excess(returns_panel([fund] + cand_syms, start=start))
|
||||||
if fund not in r.columns:
|
if fund not in r.columns:
|
||||||
return {"fund": fund, "error": "no return history in the data set",
|
return {"fund": fund, "error": "no return history in the data set",
|
||||||
"verdict": "no return history", "start": start}
|
"verdict": "no return history", "start": start}
|
||||||
y = r[fund].to_numpy()
|
y = r[fund].to_numpy()
|
||||||
dates = r.index
|
dates = r.index
|
||||||
cand = {s: r[s].to_numpy() for s in r.columns if s != fund}
|
cand = {s: r[s].to_numpy() for s in r.columns
|
||||||
|
if s != fund and s not in CASH_SLEEVES}
|
||||||
y_ok = ~np.isnan(y)
|
y_ok = ~np.isnan(y)
|
||||||
if y_ok.sum() < 252:
|
if y_ok.sum() < 252:
|
||||||
return {"fund": fund, "error": "insufficient return history",
|
return {"fund": fund, "error": "insufficient return history",
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
1340
fundlab/decompose_results_rawalpha.json
Normal file
1340
fundlab/decompose_results_rawalpha.json
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
1
fundlab/factor_results_rawalpha.json
Normal file
1
fundlab/factor_results_rawalpha.json
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -69,9 +69,19 @@ SLEEVES_V2 = list(dict.fromkeys(BROAD_SLEEVES + EXTRA_SLEEVES))
|
||||||
# short-rate exposure as huge offsetting shv/bil coefficients (shv +64 /
|
# short-rate exposure as huge offsetting shv/bil coefficients (shv +64 /
|
||||||
# bil -54) - shv (1-3m) alone carries the cash/ultra-short axis, shy
|
# bil -54) - shv (1-3m) alone carries the cash/ultra-short axis, shy
|
||||||
# keeps the 1-3y axis.
|
# keeps the 1-3y axis.
|
||||||
DROP_FROM_REGRESSION = {"vea", "vug", "finux", "bil"}
|
DROP_FROM_REGRESSION = {"vea", "vug", "finux", "bil", "shv"}
|
||||||
|
# (bil/shv are the risk-free sleeves - alphas are now computed in
|
||||||
|
# excess of the T-bill rate, where they are ~0 columns; the cash
|
||||||
|
# position shows up in the residual / the virtual CASH axis instead)
|
||||||
DRIVERS = [s for s in SLEEVES_V2 if s not in DROP_FROM_REGRESSION]
|
DRIVERS = [s for s in SLEEVES_V2 if s not in DROP_FROM_REGRESSION]
|
||||||
|
|
||||||
|
# clustering/display basis = the regression sleeves + a virtual CASH axis.
|
||||||
|
# Alphas are computed in EXCESS of the T-bill rate (decompose.excess), so
|
||||||
|
# the beta vector is the fund's NET INVESTED mix and the leftover
|
||||||
|
# (1 - sum of betas) is its cash/T-bill position: a pure money-market
|
||||||
|
# fund has all betas ~ 0 -> CASH ~ 1, a levered fund -> CASH < 0.
|
||||||
|
AXES = DRIVERS + ["cash"]
|
||||||
|
|
||||||
|
|
||||||
def _resid(y: pd.Series, X: pd.DataFrame) -> pd.Series:
|
def _resid(y: pd.Series, X: pd.DataFrame) -> pd.Series:
|
||||||
m = y.notna() & X.notna().all(axis=1)
|
m = y.notna() & X.notna().all(axis=1)
|
||||||
|
|
@ -93,6 +103,7 @@ def _panel() -> pd.DataFrame:
|
||||||
log(f"building driver panel ({len(DRIVERS)} axes)")
|
log(f"building driver panel ({len(DRIVERS)} axes)")
|
||||||
p = decompose.returns_panel(SLEEVES_V2).sort_index()
|
p = decompose.returns_panel(SLEEVES_V2).sort_index()
|
||||||
p = p[~p.index.duplicated(keep="last")][DRIVERS]
|
p = p[~p.index.duplicated(keep="last")][DRIVERS]
|
||||||
|
p = decompose.excess(p) # alphas are in excess of the T-bill rate
|
||||||
# pure vol axis: vblix residualized on the core equity/duration axes
|
# pure vol axis: vblix residualized on the core equity/duration axes
|
||||||
core = [c for c in ("ivv", "tlt") if c in p.columns]
|
core = [c for c in ("ivv", "tlt") if c in p.columns]
|
||||||
if "vblix" in p.columns and core:
|
if "vblix" in p.columns and core:
|
||||||
|
|
@ -142,11 +153,16 @@ def _beta_window(y: pd.Series, X: pd.DataFrame, start: str) -> dict | None:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def factor_screen(sym: str, start: str = "1990-01-01") -> dict | None:
|
def factor_screen(sym: str, start: str = None) -> dict | None:
|
||||||
|
if start is None:
|
||||||
|
start = decompose.FULL_WINDOW
|
||||||
fund = decompose.adj_close(sym)
|
fund = decompose.adj_close(sym)
|
||||||
if fund is None or len(fund) < 250:
|
if fund is None or len(fund) < 250:
|
||||||
return None
|
return None
|
||||||
y = fund.pct_change().dropna()
|
y = fund.pct_change().dropna()
|
||||||
|
rf = decompose.rf_series()
|
||||||
|
if rf is not None:
|
||||||
|
y = y.sub(rf.reindex(y.index).fillna(0.0))
|
||||||
X = _panel().reindex(y.index)
|
X = _panel().reindex(y.index)
|
||||||
# sleeves must have history for most of the fund's window
|
# sleeves must have history for most of the fund's window
|
||||||
avail = [c for c in X.columns if X[c].notna().mean() > 0.3]
|
avail = [c for c in X.columns if X[c].notna().mean() > 0.3]
|
||||||
|
|
|
||||||
14
fundlab/factors_run.log
Normal file
14
fundlab/factors_run.log
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
15:03:47 factor screen: 2384 funds, 2384 to do
|
||||||
|
15:03:47 building driver panel (34 axes)
|
||||||
|
15:03:55 200/2384
|
||||||
|
15:04:02 400/2384
|
||||||
|
15:04:10 600/2384
|
||||||
|
15:04:18 800/2384
|
||||||
|
15:04:30 1000/2384
|
||||||
|
15:04:43 1200/2384
|
||||||
|
15:04:52 1400/2384
|
||||||
|
15:04:59 1600/2384
|
||||||
|
15:05:07 1800/2384
|
||||||
|
15:05:14 2000/2384
|
||||||
|
15:05:21 2200/2384
|
||||||
|
15:05:28 factor screen done: 2384 funds -> factor_results.json
|
||||||
444
fundlab/narrative.py
Normal file
444
fundlab/narrative.py
Normal file
|
|
@ -0,0 +1,444 @@
|
||||||
|
"""Per-fund narrative: English prose explaining the performance and its
|
||||||
|
drivers, built from the analysis we have on file.
|
||||||
|
|
||||||
|
The prose is data-driven (every number comes from the computed results),
|
||||||
|
and it is required to be honest about limits: when the return drivers
|
||||||
|
are unknown or only weakly identified, the text says so explicitly.
|
||||||
|
|
||||||
|
Paragraphs:
|
||||||
|
1. what the fund is (name, stated strategy if on file, what its
|
||||||
|
N-PORT actually holds, which return-driver cluster it sits in)
|
||||||
|
2. the performance in plain terms (full history, 5y, recent year,
|
||||||
|
behaviour in the defined market episodes, calendar-year pattern)
|
||||||
|
3. what is driving it (fit quality -> whose exposures vs idiosyncratic
|
||||||
|
alpha; the economic meaning of the top loadings; weight stability)
|
||||||
|
4. what we do NOT know (unexplained share, alpha steadiness, sample
|
||||||
|
size, holdings opacity) - stated plainly
|
||||||
|
5. bottom line (account placement, best cluster peers, role)
|
||||||
|
|
||||||
|
Run: .venv/bin/python -m fundlab.narrative (prints all narratives)
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from fundlab import report as _r
|
||||||
|
from fundlab.searchlist import BROAD_SLEEVES
|
||||||
|
from fundlab import decompose as _dc
|
||||||
|
|
||||||
|
HERE = Path(__file__).parent
|
||||||
|
|
||||||
|
_XC = json.loads((HERE / "xcheck_report.json").read_text()) \
|
||||||
|
if (HERE / "xcheck_report.json").exists() else {}
|
||||||
|
|
||||||
|
|
||||||
|
def _pct(x, nd=1) -> str:
|
||||||
|
if x is None or (isinstance(x, float) and np.isnan(x)):
|
||||||
|
return "no data"
|
||||||
|
return f"{100 * x:+.{nd}f}%"
|
||||||
|
|
||||||
|
|
||||||
|
def _num(x, nd=2) -> str:
|
||||||
|
if x is None or (isinstance(x, float) and np.isnan(x)):
|
||||||
|
return "n/a"
|
||||||
|
return f"{x:.{nd}f}"
|
||||||
|
|
||||||
|
|
||||||
|
# short prose names for sleeves whose SLEEVE_DESC lead-in references a
|
||||||
|
# sibling ticker ("same HY exposure as VWEAX via a different fund")
|
||||||
|
_PROSE_NAME = {
|
||||||
|
"vea": "international developed markets",
|
||||||
|
"efa": "international developed markets",
|
||||||
|
"hyg": "high-yield corporate bonds",
|
||||||
|
"vweax": "high-yield corporate bonds",
|
||||||
|
"dbb": "broad commodities",
|
||||||
|
"gsg": "broad commodities",
|
||||||
|
"vblix": "crash vol (VIX futures)",
|
||||||
|
"bil": "cash (T-bills)",
|
||||||
|
"shv": "cash (T-bills)",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _sleeve_prose(sym: str, beta: float) -> str:
|
||||||
|
nm, desc = _r.sleeve_desc(sym)
|
||||||
|
short = _PROSE_NAME.get(sym)
|
||||||
|
head = short.split(";")[0].strip() if short else \
|
||||||
|
desc.split(";")[0].strip()
|
||||||
|
head = head[0].upper() + head[1:] if head else nm
|
||||||
|
if abs(beta) < 0.15:
|
||||||
|
return f"a small tilt to {head.lower()}"
|
||||||
|
if beta > 0:
|
||||||
|
return f"exposure to {head.lower()}"
|
||||||
|
return f"short-like exposure to {head.lower()} (it rises when that " \
|
||||||
|
f"asset falls)"
|
||||||
|
|
||||||
|
|
||||||
|
def _top_sleeves(fr: dict, window: str, n: int = 3) -> list[tuple[str, float]]:
|
||||||
|
f = fr.get(window) or {}
|
||||||
|
betas = f.get("betas") or {}
|
||||||
|
top = sorted(betas.items(), key=lambda kv: -abs(kv[1]))[:n]
|
||||||
|
return [(s, b) for s, b in top if abs(b) >= 0.08]
|
||||||
|
|
||||||
|
|
||||||
|
def _fit(fr: dict, srow: dict) -> tuple[float | None, float | None,
|
||||||
|
float | None]:
|
||||||
|
"""(r2, alpha_ann_5y, t5) preferring the reference-model numbers."""
|
||||||
|
r2 = srow.get("r2_5y")
|
||||||
|
a5 = srow.get("alpha_ann_5y")
|
||||||
|
t5 = srow.get("alpha_t_5y")
|
||||||
|
if not isinstance(r2, (int, float)):
|
||||||
|
r2 = (fr.get("rec5") or fr.get("full") or {}).get("r2")
|
||||||
|
if not isinstance(a5, (int, float)):
|
||||||
|
a5 = (fr.get("rec5") or fr.get("full") or {}).get("alpha_ann")
|
||||||
|
if not isinstance(t5, (int, float)):
|
||||||
|
t5 = (fr.get("rec5") or fr.get("full") or {}).get("alpha_t")
|
||||||
|
return (r2 if isinstance(r2, (int, float)) else None,
|
||||||
|
a5 if isinstance(a5, (int, float)) else None,
|
||||||
|
t5 if isinstance(t5, (int, float)) else None)
|
||||||
|
|
||||||
|
|
||||||
|
def narrate(sym: str) -> list[str]:
|
||||||
|
sym = sym.lower()
|
||||||
|
srow = _r.search_row(sym)
|
||||||
|
fr = _r.factor_row(sym)
|
||||||
|
dr = _r.decomp_row(sym)
|
||||||
|
tax = _r.tax_row(sym)
|
||||||
|
ddr = _r.dd_row(sym)
|
||||||
|
xcr = _XC.get(sym, {})
|
||||||
|
p = _r.price(sym)
|
||||||
|
name = (srow.get("name") or _r.FONDS.get(sym, {}).get("name")
|
||||||
|
or (fr or {}).get("name") or sym.upper())
|
||||||
|
out: list[str] = []
|
||||||
|
|
||||||
|
# ------------------------------------------------------------ 1. what
|
||||||
|
who = []
|
||||||
|
who.append(f"{sym.upper()} is the {name}.")
|
||||||
|
obj = (_r.FONDS.get(sym) or {}).get("objective")
|
||||||
|
if obj:
|
||||||
|
first = obj.split(". ")[0].strip().rstrip(".")
|
||||||
|
who.append(f"Stated strategy: {first}.")
|
||||||
|
if xcr and not xcr.get("error"):
|
||||||
|
b = [x["name"] for x in xcr.get("buckets", [])[:2]]
|
||||||
|
if b:
|
||||||
|
who.append(f"Per its latest N-PORT its actual holdings are "
|
||||||
|
f"mostly {b[0]}"
|
||||||
|
+ (f" and {b[1]}" if len(b) > 1 else "") + ".")
|
||||||
|
out.append(" ".join(who))
|
||||||
|
|
||||||
|
if p is None:
|
||||||
|
# no return history: do NOT claim a cluster - the loading vector
|
||||||
|
# is all zeros and would park the fund in the cash cluster
|
||||||
|
out.append("There is no local return history for this share "
|
||||||
|
"class yet (new class), so performance and drivers "
|
||||||
|
"cannot be measured from returns. The N-PORT shows "
|
||||||
|
"what it holds: " + ((dr or {}).get("note")
|
||||||
|
or "see holdings"))
|
||||||
|
return out
|
||||||
|
if sym in _r.MEMBER:
|
||||||
|
_cid, clabel, cn = _r.MEMBER[sym]
|
||||||
|
who = out[0]
|
||||||
|
out[0] = (who + f" In the return-driver analysis it sits in the "
|
||||||
|
f"'{clabel}' cluster with {cn - 1} other funds.")
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
load = _r.fund_loading_row(fr)
|
||||||
|
_cid, clabel = _r.cluster_of_row(load)
|
||||||
|
out[0] = (out[0] + f" Its return-driver signature is closest "
|
||||||
|
f"to the '{clabel}' cluster.")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
st = _r.perf_stats(p)
|
||||||
|
r2, a5, t5 = _fit(fr, srow)
|
||||||
|
tf = (fr.get("full") or {}).get("alpha_t")
|
||||||
|
a_f = (fr.get("full") or {}).get("alpha_ann")
|
||||||
|
refs = _r.ref_components(sym, fr)
|
||||||
|
r2f_ = (fr.get("rec5") or fr.get("full") or {}).get("r2")
|
||||||
|
fit = r2 if r2 is not None else r2f_
|
||||||
|
r25 = srow.get("r2_5y") if isinstance(srow.get("r2_5y"), (int, float)) \
|
||||||
|
else r2f_
|
||||||
|
refs_curve = refs if (fit is not None and fit >= 0.5) else []
|
||||||
|
mix = _r.mix_series(refs_curve) if refs_curve else _r.price("bil")
|
||||||
|
ivv = _r.price("ivv")
|
||||||
|
t5y = _r.window_ret(p, "2021-01-01", st["end"])
|
||||||
|
t1y = _r.window_ret(p, "2025-09-01", st["end"])
|
||||||
|
ref5y = _r.window_ret(mix, "2021-01-01", st["end"]) if mix is not None \
|
||||||
|
else None
|
||||||
|
iv5y = _r.window_ret(ivv, "2021-01-01", st["end"]) if ivv is not None \
|
||||||
|
else None
|
||||||
|
|
||||||
|
# --------------------------------------------------------- 2. performance
|
||||||
|
perf = []
|
||||||
|
tot = p.iloc[-1] / p.iloc[0] - 1
|
||||||
|
perf.append(
|
||||||
|
f"Since {st['start'][:4]} it has compounded at "
|
||||||
|
f"{_pct(st['cagr'])} per year (a {_pct(tot, 0)} total return) "
|
||||||
|
f"with {_pct(st['vol'], 0)} annualized volatility and a maximum "
|
||||||
|
f"drawdown of {100 * abs(st['mdd']):.0f}%.")
|
||||||
|
perf.append(
|
||||||
|
f"Over the last five years it returned {_pct(t5y)} versus "
|
||||||
|
f"{_pct(ref5y)} for its reference"
|
||||||
|
+ (f" and {_pct(iv5y)} for the S&P 500" if iv5y is not None else "")
|
||||||
|
+ f". The last twelve months have done {_pct(t1y)}.")
|
||||||
|
yrs = _r.annual_table(p, 7)
|
||||||
|
pos = sum(1 for _y, v in yrs if v > 0)
|
||||||
|
perf.append(f"It was positive in {pos} of the last {len(yrs)} "
|
||||||
|
f"calendar years (including the partial current year).")
|
||||||
|
# episodes
|
||||||
|
rets = ddr.get("rets", {})
|
||||||
|
if rets:
|
||||||
|
best = max(rets.items(), key=lambda kv: kv[1])
|
||||||
|
worst = min(rets.items(), key=lambda kv: kv[1])
|
||||||
|
perf.append(
|
||||||
|
f"Across the defined market episodes it did best in "
|
||||||
|
f"'{best[0]}' ({_pct(best[1])}) and worst in '{worst[0]}' "
|
||||||
|
f"({_pct(worst[1])}) - the peak-to-trough windows when "
|
||||||
|
f"equities fell hardest.")
|
||||||
|
_dv = ddr.get("verdict") or ""
|
||||||
|
if _dv and not _dv.startswith("CANDIDATE"):
|
||||||
|
perf.append(f"Its drawdown screen verdict: {_dv}.")
|
||||||
|
out.append(" ".join(perf))
|
||||||
|
|
||||||
|
# --------------------------------------------------------- 3. drivers
|
||||||
|
drv = []
|
||||||
|
tops = _top_sleeves(fr, "rec5", 3)
|
||||||
|
if fit is not None and fit >= 0.7:
|
||||||
|
tops_txt = ", ".join(_sleeve_prose(s, b) for s, b in tops)
|
||||||
|
drv.append(
|
||||||
|
f"The fit is strong: {100 * fit:.0f}% of its excess returns "
|
||||||
|
f"over the last five years are explained by its measured "
|
||||||
|
f"exposures"
|
||||||
|
+ (f" - {tops_txt}" if tops else "") + ".")
|
||||||
|
drv.append(
|
||||||
|
f"In other words, most of what this fund does is charge you "
|
||||||
|
f"for those exposures in the form of a fund; what is left - "
|
||||||
|
f"an alpha of {_pct(a5)} per year (t = {_num(t5, 1)}) - is "
|
||||||
|
+ ("statistically indistinguishable from zero, i.e. the "
|
||||||
|
"strategy is not clearly adding anything on top of the "
|
||||||
|
"mix it owns."
|
||||||
|
if (t5 or 0) < 1.75 else
|
||||||
|
"small relative to the beta, but it is what separates "
|
||||||
|
"this fund from the equivalent index mix.")
|
||||||
|
)
|
||||||
|
elif fit is not None and fit >= 0.5:
|
||||||
|
tops_txt = ", ".join(_sleeve_prose(s, b) for s, b in tops)
|
||||||
|
drv.append(
|
||||||
|
f"The measured exposures explain a good share but not all "
|
||||||
|
f"({100 * fit:.0f}% R²) of its excess returns."
|
||||||
|
+ (f" The main ones: {tops_txt}." if tops else ""))
|
||||||
|
drv.append(
|
||||||
|
f"The residual is {_pct(a5)} per year (t = {_num(t5, 1)}): "
|
||||||
|
+ ("a real edge on top of the mix, but a material part of "
|
||||||
|
"the performance IS the mix - judge the exposures and "
|
||||||
|
"the skill separately."
|
||||||
|
if (t5 or 0) >= 1.75 else
|
||||||
|
"not statistically distinct from noise at the five-year "
|
||||||
|
"horizon, so treat the outperformance as part beta, part "
|
||||||
|
"luck until it accumulates more history.")
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
tops_txt = ", ".join(_sleeve_prose(s, b) for s, b in tops)
|
||||||
|
drv.append(
|
||||||
|
f"The broad sleeve framework explains little of its excess "
|
||||||
|
f"returns (R² = {_num(fit) if fit is not None else 'n/a'}). "
|
||||||
|
+ (f"The loadings that do show up - {tops_txt} - are minor "
|
||||||
|
"tilts, not the story."
|
||||||
|
if tops else
|
||||||
|
"No benchmark loading is even large."))
|
||||||
|
long_ctx = ""
|
||||||
|
if isinstance(a_f, (int, float)):
|
||||||
|
long_ctx = (f" Over the full history the same estimate is "
|
||||||
|
f"{_pct(a_f)} per year (t = {_num(tf, 1)}).")
|
||||||
|
if (t5 or 0) >= 2:
|
||||||
|
drv.append(
|
||||||
|
f"The bulk of the performance is therefore "
|
||||||
|
f"idiosyncratic: it comes from the fund's own holdings "
|
||||||
|
f"and decisions, which nothing in our 34-sleeve space "
|
||||||
|
f"replicates. The estimate of that idiosyncratic return "
|
||||||
|
f"is {_pct(a5)} per year over the last five years "
|
||||||
|
f"(t = {_num(t5, 1)}) - statistically significant, so "
|
||||||
|
f"the outperformance is real; what the returns alone "
|
||||||
|
f"cannot tell us is its source.{long_ctx}")
|
||||||
|
elif (a5 or 0) >= 0:
|
||||||
|
drv.append(
|
||||||
|
f"The bulk of the performance is therefore "
|
||||||
|
f"idiosyncratic: it comes from the fund's own holdings "
|
||||||
|
f"and decisions, which nothing in our 34-sleeve space "
|
||||||
|
f"replicates. The estimate of that idiosyncratic return "
|
||||||
|
f"is {_pct(a5)} per year over the last five years "
|
||||||
|
f"(t = {_num(t5, 1)}) - at that t-stat it is not yet "
|
||||||
|
f"clearly different from a lucky streak.{long_ctx}")
|
||||||
|
else:
|
||||||
|
drv.append(
|
||||||
|
f"Most of the performance is therefore idiosyncratic "
|
||||||
|
f"rather than benchmark-like. The honest five-year read "
|
||||||
|
f"of its excess return is {_pct(a5)} per year "
|
||||||
|
f"(t = {_num(t5, 1)}): over the recent window this fund "
|
||||||
|
f"is NOT measurably adding to its fitted reference.{long_ctx}")
|
||||||
|
if (a5 or 0) < 0 and isinstance(tf, (int, float)) and tf >= 1.25:
|
||||||
|
drv.append(
|
||||||
|
f"The longer record is better: over the full history the "
|
||||||
|
f"alpha is {_pct(a_f)} per year (t = {_num(tf, 1)}), "
|
||||||
|
f"which IS significant - so the five-year estimate "
|
||||||
|
f"looks like a flat patch in a longer positive trend, "
|
||||||
|
f"not evidence the edge has gone.")
|
||||||
|
if xcr and not xcr.get("error"):
|
||||||
|
b = [x["name"] for x in xcr.get("buckets", [])[:2]]
|
||||||
|
if b:
|
||||||
|
drv.append(
|
||||||
|
f"The N-PORT is consistent with that: the alpha is "
|
||||||
|
f"plausibly coming from {b[0]}"
|
||||||
|
+ (f" and {b[1]}" if len(b) > 1 else "")
|
||||||
|
+ " - asset classes our sleeve set either does not "
|
||||||
|
"model directly or models too coarsely. That is an "
|
||||||
|
"interpretation from the holdings, not something "
|
||||||
|
"the returns prove.")
|
||||||
|
if obj and (a5 or 0) > 0:
|
||||||
|
_o = obj.split(". ")[0].rstrip(".")
|
||||||
|
if len(_o) > 110:
|
||||||
|
_o = _o[:110].rsplit(" ", 1)[0] + "..."
|
||||||
|
drv.append(
|
||||||
|
f"The stated strategy ('{_o}') is a plausible mechanism "
|
||||||
|
f"as well, but that is a hypothesis - the returns only "
|
||||||
|
f"tell us the outperformance exists, not why.")
|
||||||
|
# stability (curated funds)
|
||||||
|
roll = (dr or {}).get("rolling") or {}
|
||||||
|
if "verdict" in (dr or {}) and roll.get("max_drift") is not None:
|
||||||
|
md = roll["max_drift"]
|
||||||
|
drv.append(
|
||||||
|
f"The curated decomposition's read: {dr['verdict']}. "
|
||||||
|
f"Weight stability: the one-year rolling betas move by at "
|
||||||
|
f"most {md:.2f} (relative to the full-sample weights) - "
|
||||||
|
+ ("so the weights are roughly stable over time."
|
||||||
|
if md < 0.5 else
|
||||||
|
"so treat this as a tactically active fund, not a "
|
||||||
|
"static mix."))
|
||||||
|
out.append(" ".join(drv))
|
||||||
|
|
||||||
|
# ------------------------------------------------- 4. what we do NOT know
|
||||||
|
unk = []
|
||||||
|
if fit is not None:
|
||||||
|
if (t5 or 0) >= 2:
|
||||||
|
unk.append(
|
||||||
|
f"To be explicit about the limits: "
|
||||||
|
f"{100 * (1 - fit):.0f}% of this fund's excess return "
|
||||||
|
f"is NOT attributed to any measured exposure by our "
|
||||||
|
f"analysis - we know the outperformance is real, we do "
|
||||||
|
f"not know from returns what produces it; the source "
|
||||||
|
f"has to be read from the filings before sizing up.")
|
||||||
|
else:
|
||||||
|
unk.append(
|
||||||
|
f"To be explicit about the limits: the excess return is "
|
||||||
|
f"not measurable against noise at the current sample "
|
||||||
|
f"size, so there is not even a reliable alpha to "
|
||||||
|
f"attribute; {100 * (1 - fit):.0f}% of the return is "
|
||||||
|
f"outside our sleeve model either way.")
|
||||||
|
pf = srow.get("alpha_pos_frac")
|
||||||
|
if isinstance(pf, (int, float)) and pf < 0.60:
|
||||||
|
unk.append(
|
||||||
|
f"The alpha is also not steady: in {100 * (1 - pf):.0f}% of "
|
||||||
|
f"rolling six-month windows the fund trailed its reference, "
|
||||||
|
f"so the five-year number is carrying periods of "
|
||||||
|
f"underperformance.")
|
||||||
|
if (t5 or 0) >= 2 and isinstance(tf, (int, float)) and tf < 1.25:
|
||||||
|
unk.append(
|
||||||
|
"The significance is recent - over the full history the "
|
||||||
|
"alpha is not significant, so this is a provisional read on "
|
||||||
|
"a ~5-year sample.")
|
||||||
|
if st["years"] < 3:
|
||||||
|
unk.append(
|
||||||
|
f"The whole sample is short ({st['years']:.1f} years), so "
|
||||||
|
f"every number above has a wide error bar.")
|
||||||
|
if xcr.get("note"):
|
||||||
|
unk.append(xcr["note"].rstrip(".") + ".")
|
||||||
|
note = (dr or {}).get("note")
|
||||||
|
if note and "N-PORT" in note:
|
||||||
|
# holdings cross-check sentence (shortlist)
|
||||||
|
for sentence in note.split(". "):
|
||||||
|
if "N-PORT" in sentence or "holdings" in sentence.lower():
|
||||||
|
unk.append(sentence.strip().rstrip(".") +
|
||||||
|
" - the holdings check is the ground truth "
|
||||||
|
"here, and the return model is only a "
|
||||||
|
"description of it.")
|
||||||
|
break
|
||||||
|
if not unk:
|
||||||
|
unk.append("No major caveats beyond the usual: the past fit may "
|
||||||
|
"not persist, and the sleeves are models of the "
|
||||||
|
"fund, not the fund itself.")
|
||||||
|
out.append(" ".join(unk))
|
||||||
|
|
||||||
|
# --------------------------------------------------------- 5. bottom line
|
||||||
|
bot = []
|
||||||
|
loc = tax.get("location")
|
||||||
|
if loc:
|
||||||
|
basis = "N-PORT holdings" if tax.get("basis") == "N-PORT" \
|
||||||
|
else "the sleeve model"
|
||||||
|
if "MIXED" in loc:
|
||||||
|
bot.append(
|
||||||
|
f"Account placement: not settled by the model - the "
|
||||||
|
f"sleeve model calls it MIXED, so the last 1099-DIV is "
|
||||||
|
f"the arbiter before choosing taxable vs IRA.")
|
||||||
|
else:
|
||||||
|
bot.append(
|
||||||
|
f"Account placement: "
|
||||||
|
f"{'taxable' if 'TAXABLE' in loc else 'IRA'} "
|
||||||
|
f"({basis} says {loc}).")
|
||||||
|
# peers
|
||||||
|
if sym in _r.MEMBER:
|
||||||
|
cid = _r.MEMBER[sym][0]
|
||||||
|
members = _r.KMEANS["clusters"][cid]["syms"]
|
||||||
|
peers = []
|
||||||
|
for s in members:
|
||||||
|
if s == sym:
|
||||||
|
continue
|
||||||
|
v = _r.search_row(s)
|
||||||
|
if isinstance(v.get("alpha_t_5y"), (int, float)) and \
|
||||||
|
v["alpha_t_5y"] > 0:
|
||||||
|
pp = _r.price(s)
|
||||||
|
if pp is None:
|
||||||
|
continue
|
||||||
|
peers.append((v["alpha_t_5y"], v.get("alpha_ann_5y"), s))
|
||||||
|
peers.sort(reverse=True)
|
||||||
|
if peers:
|
||||||
|
b_t, b_a, b_s = peers[0]
|
||||||
|
bp = _r.price(b_s)
|
||||||
|
bt5 = _r.window_ret(bp, "2021-01-01",
|
||||||
|
_r.perf_stats(bp)["end"])
|
||||||
|
bot.append(
|
||||||
|
f"Within its cluster the strongest alternative is "
|
||||||
|
f"{b_s.upper()} (5y {_pct(bt5)}, alpha t = {b_t:+.1f}); "
|
||||||
|
f"the choice between them should turn on the conviction "
|
||||||
|
f"in the strategy, the tax fit and the price paid, not "
|
||||||
|
f"on the statistics - they are the same kind of "
|
||||||
|
f"position.")
|
||||||
|
cp = srow.get("corr_portfolio")
|
||||||
|
if isinstance(cp, (int, float)):
|
||||||
|
bot.append(
|
||||||
|
f"Its correlation with your current portfolio is "
|
||||||
|
f"{cp:+.2f} - "
|
||||||
|
+ ("a genuine diversifier" if cp < 0.3
|
||||||
|
else "not very diversified vs what you already own".rstrip("."))
|
||||||
|
+ ".")
|
||||||
|
out.append(" ".join(bot))
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
from fundlab.nport import FUND_TOKENS
|
||||||
|
from fundlab.decompose import ALIAS
|
||||||
|
cand = [v["sym"] for v in _r.SEARCH.values()
|
||||||
|
if isinstance(v, dict)
|
||||||
|
and str(v.get("verdict", "")).startswith("CANDIDATE")]
|
||||||
|
short = [s for s in FUND_TOKENS if s not in ALIAS]
|
||||||
|
for s in cand + short:
|
||||||
|
print(f"=== {s.upper()} ===")
|
||||||
|
for para in narrate(s):
|
||||||
|
print(para)
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
1
fundlab/overnight.pid
Normal file
1
fundlab/overnight.pid
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
5847
|
||||||
36
fundlab/overnight_rescreen.log
Normal file
36
fundlab/overnight_rescreen.log
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
15:09:56 === stage screen ===
|
||||||
|
15:09:56 screen: 2384 funds, 2384 to do
|
||||||
|
15:10:29 screen: 100/2384
|
||||||
|
15:11:01 screen: 200/2384
|
||||||
|
15:11:33 screen: 300/2384
|
||||||
|
15:12:04 screen: 400/2384
|
||||||
|
15:12:36 screen: 500/2384
|
||||||
|
15:13:09 screen: 600/2384
|
||||||
|
15:13:42 screen: 700/2384
|
||||||
|
15:14:15 screen: 800/2384
|
||||||
|
15:14:45 screen: 900/2384
|
||||||
|
15:15:20 screen: 1000/2384
|
||||||
|
15:15:56 screen: 1100/2384
|
||||||
|
15:16:31 screen: 1200/2384
|
||||||
|
15:17:07 screen: 1300/2384
|
||||||
|
15:17:38 screen: 1400/2384
|
||||||
|
15:18:14 screen: 1500/2384
|
||||||
|
15:18:45 screen: 1600/2384
|
||||||
|
15:19:16 screen: 1700/2384
|
||||||
|
15:19:47 screen: 1800/2384
|
||||||
|
15:20:19 screen: 1900/2384
|
||||||
|
15:20:51 screen: 2000/2384
|
||||||
|
15:21:23 screen: 2100/2384
|
||||||
|
15:21:54 screen: 2200/2384
|
||||||
|
15:22:26 screen: 2300/2384
|
||||||
|
15:22:53 screen done: 2384 funds
|
||||||
|
15:22:53 === stage finalize ===
|
||||||
|
15:22:53 finalize: 2384 funds screened
|
||||||
|
15:22:53 1339 sleeve mix
|
||||||
|
15:22:53 1001 weak/unstable alpha
|
||||||
|
15:22:53 17 no 5y window
|
||||||
|
15:22:53 11 CANDIDATE
|
||||||
|
15:22:53 10 alpha, but correlated with current portfolio
|
||||||
|
15:22:53 6 alpha in 5y window, but not persistent
|
||||||
|
15:22:53 candidates v1 name-filter would have missed: ['aguax', 'etsix', 'femdx', 'hicox', 'prfrx', 'puls', 'rctix', 'rpifx', 'scfzx']
|
||||||
|
15:22:53 === overnight run finished in 0.2h ===
|
||||||
98
fundlab/refback.log
Normal file
98
fundlab/refback.log
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
[2026-08-30 15:40:42] rows=2384 todo=2384
|
||||||
|
[2026-08-30 15:40:48] 25/2384 done (saved)
|
||||||
|
[2026-08-30 15:40:53] 50/2384 done (saved)
|
||||||
|
[2026-08-30 15:40:59] 75/2384 done (saved)
|
||||||
|
[2026-08-30 15:41:04] 100/2384 done (saved)
|
||||||
|
[2026-08-30 15:41:10] 125/2384 done (saved)
|
||||||
|
[2026-08-30 15:41:16] 150/2384 done (saved)
|
||||||
|
[2026-08-30 15:41:22] 175/2384 done (saved)
|
||||||
|
[2026-08-30 15:41:28] 200/2384 done (saved)
|
||||||
|
[2026-08-30 15:41:33] 225/2384 done (saved)
|
||||||
|
[2026-08-30 15:41:39] 250/2384 done (saved)
|
||||||
|
[2026-08-30 15:41:45] 275/2384 done (saved)
|
||||||
|
[2026-08-30 15:41:51] 300/2384 done (saved)
|
||||||
|
[2026-08-30 15:41:57] 325/2384 done (saved)
|
||||||
|
[2026-08-30 15:42:03] 350/2384 done (saved)
|
||||||
|
[2026-08-30 15:42:08] 375/2384 done (saved)
|
||||||
|
[2026-08-30 15:42:14] 400/2384 done (saved)
|
||||||
|
[2026-08-30 15:42:20] 425/2384 done (saved)
|
||||||
|
[2026-08-30 15:42:26] 450/2384 done (saved)
|
||||||
|
[2026-08-30 15:42:32] 475/2384 done (saved)
|
||||||
|
[2026-08-30 15:42:37] 500/2384 done (saved)
|
||||||
|
[2026-08-30 15:42:42] 525/2384 done (saved)
|
||||||
|
[2026-08-30 15:42:48] 550/2384 done (saved)
|
||||||
|
[2026-08-30 15:42:54] 575/2384 done (saved)
|
||||||
|
[2026-08-30 15:43:00] 600/2384 done (saved)
|
||||||
|
[2026-08-30 15:43:06] 625/2384 done (saved)
|
||||||
|
[2026-08-30 15:43:11] 650/2384 done (saved)
|
||||||
|
[2026-08-30 15:43:18] 675/2384 done (saved)
|
||||||
|
[2026-08-30 15:43:24] 700/2384 done (saved)
|
||||||
|
[2026-08-30 15:43:29] 725/2384 done (saved)
|
||||||
|
[2026-08-30 15:43:36] 750/2384 done (saved)
|
||||||
|
[2026-08-30 15:43:42] 775/2384 done (saved)
|
||||||
|
[2026-08-30 15:43:48] 800/2384 done (saved)
|
||||||
|
[2026-08-30 15:43:53] 825/2384 done (saved)
|
||||||
|
[2026-08-30 15:43:59] 850/2384 done (saved)
|
||||||
|
[2026-08-30 15:44:05] 875/2384 done (saved)
|
||||||
|
[2026-08-30 15:44:10] 900/2384 done (saved)
|
||||||
|
[2026-08-30 15:44:16] 925/2384 done (saved)
|
||||||
|
[2026-08-30 15:44:22] 950/2384 done (saved)
|
||||||
|
[2026-08-30 15:44:28] 975/2384 done (saved)
|
||||||
|
[2026-08-30 15:44:34] 1000/2384 done (saved)
|
||||||
|
[2026-08-30 15:44:39] 1025/2384 done (saved)
|
||||||
|
[2026-08-30 15:44:45] 1050/2384 done (saved)
|
||||||
|
[2026-08-30 15:44:51] 1075/2384 done (saved)
|
||||||
|
[2026-08-30 15:44:56] 1100/2384 done (saved)
|
||||||
|
[2026-08-30 15:45:02] 1125/2384 done (saved)
|
||||||
|
[2026-08-30 15:45:08] 1150/2384 done (saved)
|
||||||
|
[2026-08-30 15:45:14] 1175/2384 done (saved)
|
||||||
|
[2026-08-30 15:45:19] 1200/2384 done (saved)
|
||||||
|
[2026-08-30 15:45:25] 1225/2384 done (saved)
|
||||||
|
[2026-08-30 15:45:31] 1250/2384 done (saved)
|
||||||
|
[2026-08-30 15:45:36] 1275/2384 done (saved)
|
||||||
|
[2026-08-30 15:45:42] 1300/2384 done (saved)
|
||||||
|
[2026-08-30 15:45:47] 1325/2384 done (saved)
|
||||||
|
[2026-08-30 15:45:53] 1350/2384 done (saved)
|
||||||
|
[2026-08-30 15:45:59] 1375/2384 done (saved)
|
||||||
|
[2026-08-30 15:46:04] 1400/2384 done (saved)
|
||||||
|
[2026-08-30 15:46:10] 1425/2384 done (saved)
|
||||||
|
[2026-08-30 15:46:16] 1450/2384 done (saved)
|
||||||
|
[2026-08-30 15:46:22] 1475/2384 done (saved)
|
||||||
|
[2026-08-30 15:46:28] 1500/2384 done (saved)
|
||||||
|
[2026-08-30 15:46:33] 1525/2384 done (saved)
|
||||||
|
[2026-08-30 15:46:38] 1550/2384 done (saved)
|
||||||
|
[2026-08-30 15:46:44] 1575/2384 done (saved)
|
||||||
|
[2026-08-30 15:46:49] 1600/2384 done (saved)
|
||||||
|
[2026-08-30 15:46:55] 1625/2384 done (saved)
|
||||||
|
[2026-08-30 15:47:01] 1650/2384 done (saved)
|
||||||
|
[2026-08-30 15:47:06] 1675/2384 done (saved)
|
||||||
|
[2026-08-30 15:47:12] 1700/2384 done (saved)
|
||||||
|
[2026-08-30 15:47:18] 1725/2384 done (saved)
|
||||||
|
[2026-08-30 15:47:24] 1750/2384 done (saved)
|
||||||
|
[2026-08-30 15:47:30] 1775/2384 done (saved)
|
||||||
|
[2026-08-30 15:47:35] 1800/2384 done (saved)
|
||||||
|
[2026-08-30 15:47:41] 1825/2384 done (saved)
|
||||||
|
[2026-08-30 15:47:47] 1850/2384 done (saved)
|
||||||
|
[2026-08-30 15:47:53] 1875/2384 done (saved)
|
||||||
|
[2026-08-30 15:47:59] 1900/2384 done (saved)
|
||||||
|
[2026-08-30 15:48:05] 1925/2384 done (saved)
|
||||||
|
[2026-08-30 15:48:10] 1950/2384 done (saved)
|
||||||
|
[2026-08-30 15:48:16] 1975/2384 done (saved)
|
||||||
|
[2026-08-30 15:48:22] 2000/2384 done (saved)
|
||||||
|
[2026-08-30 15:48:28] 2025/2384 done (saved)
|
||||||
|
[2026-08-30 15:48:33] 2050/2384 done (saved)
|
||||||
|
[2026-08-30 15:48:39] 2075/2384 done (saved)
|
||||||
|
[2026-08-30 15:48:45] 2100/2384 done (saved)
|
||||||
|
[2026-08-30 15:48:51] 2125/2384 done (saved)
|
||||||
|
[2026-08-30 15:48:57] 2150/2384 done (saved)
|
||||||
|
[2026-08-30 15:49:03] 2175/2384 done (saved)
|
||||||
|
[2026-08-30 15:49:09] 2200/2384 done (saved)
|
||||||
|
[2026-08-30 15:49:15] 2225/2384 done (saved)
|
||||||
|
[2026-08-30 15:49:21] 2250/2384 done (saved)
|
||||||
|
[2026-08-30 15:49:27] 2275/2384 done (saved)
|
||||||
|
[2026-08-30 15:49:33] 2300/2384 done (saved)
|
||||||
|
[2026-08-30 15:49:38] 2325/2384 done (saved)
|
||||||
|
[2026-08-30 15:49:44] 2350/2384 done (saved)
|
||||||
|
[2026-08-30 15:49:50] 2375/2384 done (saved)
|
||||||
|
[2026-08-30 15:49:52] 2384/2384 done (saved)
|
||||||
|
[2026-08-30 15:49:52] done: 2384 rows carry a reference
|
||||||
76
fundlab/refback.py
Normal file
76
fundlab/refback.py
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
"""Backfill the per-fund alpha REFERENCE into search_all.json.
|
||||||
|
|
||||||
|
The alpha search verdict (fundlab/search.py) computes alpha as the OLS
|
||||||
|
intercept of the fund's daily total returns against the sleeves BIC
|
||||||
|
forward-selection picked from the 21 broad sleeve axes (the same set for
|
||||||
|
every fund). The picked sleeves ARE the fund's reference - a fitted
|
||||||
|
sleeve mix, not a single index - but the screen never stored them, so
|
||||||
|
the app couldn't show them.
|
||||||
|
|
||||||
|
This script recomputes the forward selection (full + last-5y) for every
|
||||||
|
screened fund and stores a compact, human-readable reference string on
|
||||||
|
each row:
|
||||||
|
|
||||||
|
ref_5y "ivv +0.62, tlt +0.31" (sleeves picked for the 5y model)
|
||||||
|
ref_full "ivv +0.38, efa +0.15, ..."
|
||||||
|
"pure alpha (no sleeve selected)" when the model has no components
|
||||||
|
|
||||||
|
Resumable: rows that already carry ref_5y are skipped.
|
||||||
|
|
||||||
|
Run: .venv/bin/python -m fundlab.refback (logs to fundlab/refback.log)
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
|
||||||
|
from fundlab import decompose
|
||||||
|
from fundlab.searchlist import BROAD_SLEEVES
|
||||||
|
|
||||||
|
HERE = __import__("pathlib").Path(__file__).parent
|
||||||
|
SRC = HERE / "search_all.json"
|
||||||
|
LOG = HERE / "refback.log"
|
||||||
|
|
||||||
|
|
||||||
|
def log(msg: str) -> None:
|
||||||
|
line = f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] {msg}"
|
||||||
|
print(line, flush=True)
|
||||||
|
with LOG.open("a") as f:
|
||||||
|
f.write(line + "\n")
|
||||||
|
|
||||||
|
|
||||||
|
def _fmt(m: dict) -> str:
|
||||||
|
comps = m.get("components") or []
|
||||||
|
if not comps:
|
||||||
|
return "pure alpha (no sleeve selected)"
|
||||||
|
return ", ".join(f"{c['sym']} {c['beta']:+.2f}" for c in comps)
|
||||||
|
|
||||||
|
|
||||||
|
def run() -> None:
|
||||||
|
d = json.loads(SRC.read_text())
|
||||||
|
todo = [k for k, v in d.items()
|
||||||
|
if isinstance(v, dict)
|
||||||
|
and isinstance(v.get("r2_5y"), (int, float))
|
||||||
|
and "ref_5y" not in v]
|
||||||
|
log(f"rows={len(d)} todo={len(todo)}")
|
||||||
|
for i, k in enumerate(todo, 1):
|
||||||
|
sym = d[k]["sym"]
|
||||||
|
try:
|
||||||
|
rec = decompose.decompose(sym, start=decompose.RECENT_WINDOW,
|
||||||
|
candidates={sym: BROAD_SLEEVES})
|
||||||
|
full = decompose.decompose(sym, candidates={sym: BROAD_SLEEVES})
|
||||||
|
d[k]["ref_5y"] = _fmt(rec)
|
||||||
|
d[k]["ref_full"] = _fmt(full)
|
||||||
|
except Exception as e: # noqa: BLE001 - batch must not die
|
||||||
|
d[k]["ref_5y"] = f"(backfill failed: {e})"
|
||||||
|
if i % 25 == 0 or i == len(todo):
|
||||||
|
SRC.write_text(json.dumps(d, indent=1))
|
||||||
|
log(f"{i}/{len(todo)} done (saved)")
|
||||||
|
SRC.write_text(json.dumps(d, indent=1))
|
||||||
|
n = sum(1 for v in d.values()
|
||||||
|
if isinstance(v, dict) and v.get("ref_5y"))
|
||||||
|
log(f"done: {n} rows carry a reference")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
run()
|
||||||
835
fundlab/report.py
Normal file
835
fundlab/report.py
Normal file
|
|
@ -0,0 +1,835 @@
|
||||||
|
"""Fund report: candidates + shortlist, self-contained HTML.
|
||||||
|
|
||||||
|
One section per fund:
|
||||||
|
- equity curve over the maximum available period (fund vs its fitted
|
||||||
|
reference mix vs IVV),
|
||||||
|
- performance: full history, calendar years, and the defined market
|
||||||
|
episodes (2022 bear, 2023 rate shock, 2024 vol spike, 2025 tariff
|
||||||
|
crash, 2026 Q1) - fund vs reference mix vs IVV, with the fund-vs-
|
||||||
|
reference gap (period alpha/timing),
|
||||||
|
- what drove it: the excess-of-T-bill sleeve loadings (full + 5y),
|
||||||
|
alpha + t, R^2, rolling drift, verdict,
|
||||||
|
- the reference mix explained: each picked sleeve with what it
|
||||||
|
actually exposes you to (not just the ticker),
|
||||||
|
- tax character + taxable/IRA placement,
|
||||||
|
- cluster peers: the 3-4 best funds of the same k=30 return-driver
|
||||||
|
cluster, compared, with this fund's advantages/disadvantages.
|
||||||
|
|
||||||
|
Run: .venv/bin/python -m fundlab.report -> reports/fund_report.html
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import html
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
from fundlab import cluster as _cl
|
||||||
|
from fundlab import decompose
|
||||||
|
from fundlab import factors
|
||||||
|
from fundlab.searchlist import BROAD_SLEEVES
|
||||||
|
|
||||||
|
HERE = Path(__file__).parent
|
||||||
|
REPORTS = HERE.parent / "reports"
|
||||||
|
REPORTS.mkdir(exist_ok=True)
|
||||||
|
OUT = REPORTS / "fund_report.html"
|
||||||
|
|
||||||
|
TAX = json.loads((HERE / "taxplan_results.json").read_text())
|
||||||
|
DD = json.loads((HERE / "drawdown_results.json").read_text())
|
||||||
|
FACTOR = json.loads((HERE / "factor_results.json").read_text())
|
||||||
|
SEARCH = json.loads((HERE / "search_all.json").read_text())
|
||||||
|
DECOMP = json.loads((HERE / "decompose_results.json").read_text())
|
||||||
|
FONDS = json.loads((HERE.parent / "funds.json").read_text())
|
||||||
|
KMEANS = json.loads((HERE / "cluster_kmeans.json").read_text())
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------ sleeves
|
||||||
|
# what each sleeve actually EXPOSES you to (the report must explain the
|
||||||
|
# exposure, not just name the ticker)
|
||||||
|
SLEEVE_DESC = {
|
||||||
|
"qqq": ("US large growth (Nasdaq-100)",
|
||||||
|
"growth/tech-heavy US equities; high sensitivity to earnings "
|
||||||
|
"surprises and long-end rates (duration of growth cash flows)"),
|
||||||
|
"ivv": ("US large blend (S&P 500)",
|
||||||
|
"core US equity market; the default 'own the economy' exposure"),
|
||||||
|
"iwm": ("US small cap (Russell 2000)",
|
||||||
|
"small-cap cycle: domestic credit, margin pressure, IPO window"),
|
||||||
|
"vea": ("Intl developed ex-US (Vanguard)",
|
||||||
|
"developed-market equities outside the US (EU, Japan, UK); FX-"
|
||||||
|
"hedged-off, currency moves matter"),
|
||||||
|
"efa": ("Intl developed ex-US (MSCI EAFE)",
|
||||||
|
"developed-market equities outside the US; same exposure as VEA "
|
||||||
|
"via a different index provider"),
|
||||||
|
"vwo": ("Emerging-market equity",
|
||||||
|
"EM corporate profits + EM currency + China/FX flows; "
|
||||||
|
"high-vol, high-carry, dollar-sensitive"),
|
||||||
|
"vnq": ("US REITs",
|
||||||
|
"physical real estate: rents vs rates, leverage in the property "
|
||||||
|
"sector; equity-like income"),
|
||||||
|
"bil": ("1-3 month T-bills (cash)",
|
||||||
|
"the risk-free rate itself; ~zero volatility, pure carry"),
|
||||||
|
"shv": ("0-3 month T-bills (ultra-short cash)",
|
||||||
|
"the risk-free rate itself; netted out of the excess-return "
|
||||||
|
"regression, shown only as part of a fund's cash position"),
|
||||||
|
"shy": ("1-3 year Treasuries (short duration)",
|
||||||
|
"short duration: modest rate sensitivity, ~cash-plus-carry"),
|
||||||
|
"ief": ("7-10 year Treasuries (core duration)",
|
||||||
|
"the core rate bet: price moves when the Fed path changes"),
|
||||||
|
"tlt": ("20+ year Treasuries (long duration)",
|
||||||
|
"levered duration: big moves on rate expectations, steepener/"
|
||||||
|
"bull-steepener exposure"),
|
||||||
|
"vblix": ("VIX futures (pure vol axis)",
|
||||||
|
"crash insurance / short-vol funding; positive loading = "
|
||||||
|
"long-vol (rises in panic), negative = short-vol carry"),
|
||||||
|
"agg": ("Aggregate bonds (Treasuries + IG credit)",
|
||||||
|
"the core bond market: ~60% Treasuries, IG corporates, MBS; "
|
||||||
|
"moderate duration"),
|
||||||
|
"vweax": ("High-yield corporate bonds",
|
||||||
|
"credit spread cycle: HY junk yields, default risk in "
|
||||||
|
"recessions, strong carry in stable times"),
|
||||||
|
"hyg": ("High-yield corporate bonds (iShares)",
|
||||||
|
"same HY credit-spread exposure as VWEAX via a different fund"),
|
||||||
|
"vmbix": ("Agency RMBS (mortgage-backed)",
|
||||||
|
"mortgage credit + prepayment/extension risk; the refi cycle"),
|
||||||
|
"lqd": ("Investment-grade corporate bonds",
|
||||||
|
"IG credit spreads over Treasuries; milder default risk than HY"),
|
||||||
|
"finux": ("Intl bonds (Fidelity; TERMINATED 2017)",
|
||||||
|
"non-US credit/duration; data ends 2017 so recent windows "
|
||||||
|
"never use it"),
|
||||||
|
"pff": ("Preferred stocks",
|
||||||
|
"hybrid: fixed-rate equity-like instruments; rate + credit + "
|
||||||
|
"equity risk in one"),
|
||||||
|
"emb": ("Emerging-market debt",
|
||||||
|
"EM sovereign/corporate carry; EM currency + dollar cycle"),
|
||||||
|
"tip": ("TIPS (inflation-linked Treasuries)",
|
||||||
|
"breakeven inflation exposure: rises when inflation "
|
||||||
|
"expectations rise"),
|
||||||
|
"vtv": ("US value",
|
||||||
|
"cheap/asset-rich US names (financials, energy, cyclicals); "
|
||||||
|
"value-vs-growth style cycle"),
|
||||||
|
"dbmf": ("CTA / managed futures",
|
||||||
|
"trend-following across futures; long in crises, earns "
|
||||||
|
"un-correlated carry otherwise"),
|
||||||
|
"dbb": ("Broad commodities",
|
||||||
|
"commodity basket: inflation hedge + global growth proxy"),
|
||||||
|
"djp": ("Natural gas",
|
||||||
|
"a single volatile commodity: winter/hedging cycles"),
|
||||||
|
"gsg": ("Broad commodities (SPDR)",
|
||||||
|
"same commodity exposure as DBB via a different fund"),
|
||||||
|
"gld": ("Gold",
|
||||||
|
"crisis/inflation hedge; real-rate sensitive, no yield"),
|
||||||
|
"fxe": ("Long euros vs the dollar",
|
||||||
|
"EUR/USD: carries the euro interest-rate differential"),
|
||||||
|
"fxy": ("Long yen vs the dollar",
|
||||||
|
"USD/JPY: carries the Japan rate differential; carry-trade "
|
||||||
|
"crowding risk"),
|
||||||
|
"xlk": ("US tech sector", "the tech sector index"),
|
||||||
|
"xlf": ("US financials sector", "banks/insurance: rate + credit cycle"),
|
||||||
|
"xle": ("US energy sector", "oil prices + US drilling"),
|
||||||
|
"xlv": ("US healthcare sector", "defensive pharma/providers"),
|
||||||
|
"xlp": ("US staples sector", "defensive consumer"),
|
||||||
|
"xlu": ("US utilities sector", "bond-proxy utilities; rate sensitive"),
|
||||||
|
"xly": ("US consumer discretionary", "cyclicals: autos, retail, "
|
||||||
|
"leisure; earnings cycle"),
|
||||||
|
"xlb": ("US materials sector", "industrial materials: capex cycle"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def sleeve_desc(sym: str) -> tuple[str, str]:
|
||||||
|
return SLEEVE_DESC.get(sym, (sym.upper(), "no description on file"))
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------ data
|
||||||
|
def price(sym: str) -> pd.Series | None:
|
||||||
|
f = decompose.DATA / f"{sym.lower()}-history.csv"
|
||||||
|
if not f.exists():
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
s = (pd.read_csv(f, parse_dates=["Date"], index_col="Date")
|
||||||
|
["Adj Close"].dropna())
|
||||||
|
s = s[~s.index.duplicated(keep="last")].sort_index()
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
return s if len(s) > 40 else None
|
||||||
|
|
||||||
|
|
||||||
|
EPISODES = [] # (label, start, end) from the drawdown engine
|
||||||
|
for _e in DD["episodes"]:
|
||||||
|
EPISODES.append((_e["label"], pd.Timestamp(_e["peak"]),
|
||||||
|
pd.Timestamp(_e["trough"])))
|
||||||
|
|
||||||
|
# k=30 cluster membership (sym -> cluster id/label)
|
||||||
|
MEMBER = {}
|
||||||
|
for _c, _v in KMEANS["clusters"].items():
|
||||||
|
for _s in _v["syms"]:
|
||||||
|
MEMBER[_s] = (_c, _v["label"], _v["n"])
|
||||||
|
|
||||||
|
|
||||||
|
def loading_matrix_cached():
|
||||||
|
return _cl.loading_matrix()
|
||||||
|
|
||||||
|
|
||||||
|
CENTROIDS = {} # sym -> (cluster, centroid) for NEW points
|
||||||
|
|
||||||
|
|
||||||
|
def _centroids(syms: list[str], V: np.ndarray) -> dict[int, np.ndarray]:
|
||||||
|
lab = _cl.kmeans(_cl.emphasized(V, _cl.AXES.index("cash")), 30)
|
||||||
|
out = {}
|
||||||
|
for c in range(30):
|
||||||
|
idx = [i for i, l in enumerate(lab) if l == c]
|
||||||
|
if idx:
|
||||||
|
out[c] = np.median(V[idx], 0)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def cluster_of_row(row: np.ndarray) -> tuple[str, str]:
|
||||||
|
"""Assign a new loading row to the k=30 scheme (distance to cluster
|
||||||
|
medians in the emphasized space)."""
|
||||||
|
global CENTROIDS
|
||||||
|
if not CENTROIDS:
|
||||||
|
syms, V = loading_matrix_cached()
|
||||||
|
CENTROIDS = _centroids(syms, V)
|
||||||
|
r = row.copy()
|
||||||
|
r[_cl.AXES.index("cash")] *= _cl.CASH_EMPHASIS
|
||||||
|
best, bd = None, None
|
||||||
|
for c, cent in CENTROIDS.items():
|
||||||
|
d = float(np.sum((r - cent) ** 2))
|
||||||
|
if bd is None or d < bd:
|
||||||
|
best, bd = c, d
|
||||||
|
for c, v in KMEANS["clusters"].items():
|
||||||
|
if int(c) == best:
|
||||||
|
return (c, v["label"])
|
||||||
|
return (str(best), "?")
|
||||||
|
|
||||||
|
|
||||||
|
def factor_row(sym: str) -> dict:
|
||||||
|
"""Full + 5y excess-of-T-bill loadings for ANY fund (shortlist funds
|
||||||
|
are not in the 2,384 factor file)."""
|
||||||
|
if sym in FACTOR:
|
||||||
|
return FACTOR[sym]
|
||||||
|
r = factors.factor_screen(sym)
|
||||||
|
return r or {}
|
||||||
|
|
||||||
|
|
||||||
|
_FWD: dict = {}
|
||||||
|
|
||||||
|
|
||||||
|
def ref_components(sym: str, fr: dict, window: str = "rec5") -> list[dict]:
|
||||||
|
"""The fund's FORWARD-SELECTED reference (the mix its alpha is
|
||||||
|
measured against): BIC-gated selection from the 21 broad sleeves,
|
||||||
|
excess-of-T-bill. Recomputed (cached) because the screen stored only
|
||||||
|
the display strings. Falls back to the 34-sleeve OLS loadings when
|
||||||
|
the fund is not in the search universe."""
|
||||||
|
key = (sym, window)
|
||||||
|
if key in _FWD:
|
||||||
|
return _FWD[key]
|
||||||
|
out = None
|
||||||
|
try:
|
||||||
|
m = decompose.decompose(sym, start=decompose.RECENT_WINDOW
|
||||||
|
if window == "rec5" else None,
|
||||||
|
candidates={sym: BROAD_SLEEVES})
|
||||||
|
if m.get("components"):
|
||||||
|
out = [{"sym": c["sym"], "beta": c["beta"]}
|
||||||
|
for c in m["components"]]
|
||||||
|
except Exception:
|
||||||
|
out = None
|
||||||
|
if out is None:
|
||||||
|
comps = (fr.get(window) or fr.get("full") or {}).get("betas") or {}
|
||||||
|
out = [{"sym": s, "beta": b} for s, b in sorted(
|
||||||
|
comps.items(), key=lambda kv: -abs(kv[1])) if abs(b) >= 0.08]
|
||||||
|
_FWD[key] = out
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def search_row(sym: str) -> dict:
|
||||||
|
return SEARCH.get(sym, {})
|
||||||
|
|
||||||
|
|
||||||
|
def decomp_row(sym: str) -> dict:
|
||||||
|
return DECOMP.get(sym, {})
|
||||||
|
|
||||||
|
|
||||||
|
def tax_row(sym: str) -> dict:
|
||||||
|
up = sym.upper()
|
||||||
|
if up in TAX["shortlist"]:
|
||||||
|
return TAX["shortlist"][up]
|
||||||
|
for k in (sym, up, sym.lower()):
|
||||||
|
if k in TAX["candidates"]:
|
||||||
|
return TAX["candidates"][k]
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
def dd_row(sym: str) -> dict:
|
||||||
|
return DD["funds"].get(sym, {})
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------ stats
|
||||||
|
def perf_stats(p: pd.Series, rf_annual: float = 0.037) -> dict:
|
||||||
|
r = p.pct_change().dropna()
|
||||||
|
years = (p.index[-1] - p.index[0]).days / 365.25
|
||||||
|
cagr = (p.iloc[-1] / p.iloc[0]) ** (1 / years) - 1 if years > 0.5 else np.nan
|
||||||
|
vol = r.std() * np.sqrt(252)
|
||||||
|
roll_max = p.cummax()
|
||||||
|
mdd = float(((p / roll_max) - 1).min())
|
||||||
|
sharpe = (cagr - rf_annual) / vol if vol > 0 else np.nan
|
||||||
|
return {"start": str(p.index[0].date()), "end": str(p.index[-1].date()),
|
||||||
|
"years": years, "cagr": cagr, "vol": vol, "mdd": mdd,
|
||||||
|
"sharpe": sharpe}
|
||||||
|
|
||||||
|
|
||||||
|
def window_ret(p: pd.Series, a, b) -> float | None:
|
||||||
|
s = p[(p.index >= a) & (p.index <= b)]
|
||||||
|
if len(s) < 2:
|
||||||
|
return None
|
||||||
|
return float(s.iloc[-1] / s.iloc[0] - 1)
|
||||||
|
|
||||||
|
|
||||||
|
def annual_table(p: pd.Series, n: int = 8) -> list[tuple[str, float]]:
|
||||||
|
yr = p.resample("YE").last().dropna()
|
||||||
|
out = []
|
||||||
|
for i in range(len(yr) - 1):
|
||||||
|
lab = str(yr.index[i].year)
|
||||||
|
if i == 0:
|
||||||
|
continue
|
||||||
|
out.append((lab, float(yr.iloc[i] / yr.iloc[i - 1] - 1)))
|
||||||
|
# partial current year from last full year-end
|
||||||
|
out.append(("YTD", float(p.iloc[-1] / yr.iloc[-1] - 1)))
|
||||||
|
return out[-(n + 1):]
|
||||||
|
|
||||||
|
|
||||||
|
def mix_series(refs: list[dict]) -> pd.Series | None:
|
||||||
|
"""Fitted reference mix: sum of beta * sleeve daily returns, cumulated
|
||||||
|
to a price path (rebased 100). Pure beta path - the fund minus this
|
||||||
|
is the alpha path."""
|
||||||
|
if not refs:
|
||||||
|
b = price("bil")
|
||||||
|
if b is None:
|
||||||
|
return None
|
||||||
|
return 100 * b / b.iloc[0]
|
||||||
|
idx = None
|
||||||
|
for c in refs:
|
||||||
|
p = price(c["sym"])
|
||||||
|
if p is None:
|
||||||
|
continue
|
||||||
|
r = c["beta"] * p.pct_change()
|
||||||
|
idx = r if idx is None else idx.combine(r, lambda x, y: x + y,
|
||||||
|
fill_value=0.0)
|
||||||
|
if idx is None:
|
||||||
|
return None
|
||||||
|
idx = idx.fillna(0.0)
|
||||||
|
path = (1 + idx).cumprod()
|
||||||
|
return 100 * path / path.iloc[0]
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------ html
|
||||||
|
PLOTLY_JS = ""
|
||||||
|
|
||||||
|
|
||||||
|
def load_plotly():
|
||||||
|
global PLOTLY_JS
|
||||||
|
try:
|
||||||
|
import plotly
|
||||||
|
PLOTLY_JS = plotly.offline.get_plotlyjs()
|
||||||
|
except Exception:
|
||||||
|
PLOTLY_JS = None
|
||||||
|
|
||||||
|
|
||||||
|
def fig_html(fig, h: int = 420) -> str:
|
||||||
|
import plotly.io as pio
|
||||||
|
s = pio.to_html(fig, full_html=False, include_plotlyjs=False,
|
||||||
|
config={"displayModeBar": False}, div_id="")
|
||||||
|
return s.replace("<div>", f'<div style="height:{h}px">')
|
||||||
|
|
||||||
|
|
||||||
|
def equity_figure(sym: str, name: str, refs: list[dict]) -> str:
|
||||||
|
import plotly.graph_objects as go
|
||||||
|
p = price(sym)
|
||||||
|
if p is None:
|
||||||
|
return "<p>No local price history.</p>"
|
||||||
|
fig = go.Figure()
|
||||||
|
fig.add_trace(go.Scatter(x=p.index, y=100 * p / p.iloc[0],
|
||||||
|
name=sym.upper(), line=dict(width=2)))
|
||||||
|
m = mix_series(refs)
|
||||||
|
if m is not None:
|
||||||
|
fig.add_trace(go.Scatter(x=m.index, y=m, name="fitted reference",
|
||||||
|
line=dict(width=1.2, dash="dash")))
|
||||||
|
iv = price("ivv")
|
||||||
|
if iv is not None:
|
||||||
|
fig.add_trace(go.Scatter(
|
||||||
|
x=iv.index, y=100 * iv / iv.iloc[0], name="IVV (S&P 500)",
|
||||||
|
line=dict(width=1, dash="dot"), opacity=0.7))
|
||||||
|
fig.update_layout(height=430, margin=dict(l=10, r=10, t=30, b=10),
|
||||||
|
title=f"{html.escape(name)} - total return since "
|
||||||
|
f"{p.index[0].year} (rebased 100)",
|
||||||
|
legend=dict(orientation="h", y=1.08),
|
||||||
|
hovermode="x unified")
|
||||||
|
return fig_html(fig)
|
||||||
|
|
||||||
|
|
||||||
|
def fmt_pct(x, nd=1, sign=True):
|
||||||
|
if x is None or (isinstance(x, float) and np.isnan(x)):
|
||||||
|
return "—"
|
||||||
|
s = f"{100 * x:+.{nd}f}%" if sign else f"{100 * x:.{nd}f}%"
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def fmt_r2(x):
|
||||||
|
return "—" if x is None or (isinstance(x, float) and np.isnan(x)) \
|
||||||
|
else f"{x:.2f}"
|
||||||
|
|
||||||
|
|
||||||
|
def perf_table(p: pd.Series, refs: list[dict]) -> str:
|
||||||
|
m = mix_series(refs)
|
||||||
|
iv = price("ivv")
|
||||||
|
rows = []
|
||||||
|
|
||||||
|
def add(label, a, b, ann=False):
|
||||||
|
fr_ = window_ret(p, a, b)
|
||||||
|
mr = window_ret(m, a, b) if m is not None else None
|
||||||
|
ir = window_ret(iv, a, b) if iv is not None else None
|
||||||
|
gap = (fr_ - mr) if (fr_ is not None and mr is not None) else None
|
||||||
|
rows.append(f"<tr><td>{label}</td>"
|
||||||
|
f"<td>{fmt_pct(fr_)}</td><td>{fmt_pct(mr)}</td>"
|
||||||
|
f"<td>{fmt_pct(ir)}</td><td>{fmt_pct(gap)}</td></tr>")
|
||||||
|
|
||||||
|
st = perf_stats(p)
|
||||||
|
add("Full history", st["start"], st["end"])
|
||||||
|
add("Last 5y", "2021-01-01", st["end"])
|
||||||
|
add("Last 1y", "2025-09-01", st["end"])
|
||||||
|
for lab, a, b in EPISODES:
|
||||||
|
add(lab, a, b)
|
||||||
|
# calendar years (last 6)
|
||||||
|
yr = p.resample("YE").last().dropna()
|
||||||
|
years = [str(yr.index[i].year) for i in range(1, len(yr))][-6:]
|
||||||
|
for i, y in enumerate(years):
|
||||||
|
a = f"{y}-01-01"
|
||||||
|
b = f"{int(y) + 1}-01-01" if i < len(years) - 1 else st["end"]
|
||||||
|
add(y, a, b)
|
||||||
|
return ('<table><tr><th>period</th><th>fund</th><th>reference</th>'
|
||||||
|
'<th>IVV</th><th>fund − ref</th></tr>' + "".join(rows)
|
||||||
|
+ '</table><p class="small">fund − reference = period '
|
||||||
|
'alpha/timing (the part of that period the sleeve mix does '
|
||||||
|
'not explain). IVV shown for scale - for non-equity funds '
|
||||||
|
'the IVV column is only context.</p>')
|
||||||
|
|
||||||
|
|
||||||
|
def drivers_section(fr: dict, dr: dict, srow: dict) -> str:
|
||||||
|
out = []
|
||||||
|
if srow:
|
||||||
|
a5 = srow.get("alpha_ann_5y")
|
||||||
|
t5 = srow.get("alpha_t_5y")
|
||||||
|
r25 = srow.get("r2_5y")
|
||||||
|
if isinstance(r25, (int, float)) or isinstance(a5, (int, float)):
|
||||||
|
out.append(
|
||||||
|
f"<p><b>Reference model, last 5 years:</b> R² = "
|
||||||
|
f"{fmt_r2(r25 if isinstance(r25, (int, float)) else None)}, "
|
||||||
|
f"alpha = {fmt_pct(a5) if isinstance(a5, (int, float)) else '—'}"
|
||||||
|
f"{' (t = ' + format(t5, '+.1f') + ')' if isinstance(t5, (int, float)) else ''} "
|
||||||
|
f"vs the fitted reference mix (next section).")
|
||||||
|
rf = (fr.get("full") or {}).get("alpha_ann")
|
||||||
|
tf = (fr.get("full") or {}).get("alpha_t")
|
||||||
|
r2f = srow.get("r2_full")
|
||||||
|
if isinstance(r2f, (int, float)) or isinstance(rf, (int, float)):
|
||||||
|
out.append(
|
||||||
|
f"<p><b>Reference model, full history:</b> R² = "
|
||||||
|
f"{fmt_r2(r2f if isinstance(r2f, (int, float)) else None)}, "
|
||||||
|
f"alpha = {fmt_pct(rf) if isinstance(rf, (int, float)) else '—'}"
|
||||||
|
f"{' (t = ' + format(tf, '+.1f') + ')' if isinstance(tf, (int, float)) else ''}.</p>")
|
||||||
|
f = fr.get("rec5") or {}
|
||||||
|
betas = f.get("betas") or {}
|
||||||
|
top = sorted(betas.items(), key=lambda kv: -abs(kv[1]))[:6]
|
||||||
|
if top:
|
||||||
|
out.append(
|
||||||
|
"<p><b>Return-driver signature (34 sleeves, for clustering "
|
||||||
|
"context):</b> " + ", ".join(
|
||||||
|
f"{s} {b:+.2f}" for s, b in top) + " - net cash "
|
||||||
|
f"{1 - sum(betas.values()):+.2f}.</p>")
|
||||||
|
# drift + verdict from the curated decomposition, when available
|
||||||
|
if dr and "verdict" in dr:
|
||||||
|
out.append(f"<p><b>Decomposition verdict:</b> "
|
||||||
|
f"{html.escape(dr['verdict'])}</p>")
|
||||||
|
roll = dr.get("rolling") or {}
|
||||||
|
if roll.get("max_drift") is not None:
|
||||||
|
out.append(
|
||||||
|
f"<p>Weight stability: max 1y β-drift = "
|
||||||
|
f"{roll['max_drift']:.2f} (relative to full-sample β; "
|
||||||
|
f"0 = perfectly stable, >1 = the weight is unstable).</p>")
|
||||||
|
note = dr.get("note")
|
||||||
|
if note:
|
||||||
|
out.append(f"<p class='small'>{html.escape(note)}</p>")
|
||||||
|
if srow:
|
||||||
|
v = str(srow.get("verdict", ""))
|
||||||
|
if v:
|
||||||
|
out.append(f"<p><b>Screen verdict:</b> {html.escape(v)}</p>")
|
||||||
|
return "".join(out)
|
||||||
|
|
||||||
|
|
||||||
|
def reference_section(refs: list[dict], refs_curve: list[dict],
|
||||||
|
sym: str) -> str:
|
||||||
|
weak = bool(refs) and not refs_curve
|
||||||
|
caveat = ""
|
||||||
|
if weak:
|
||||||
|
caveat = ("<p class='small'><b>Weak fit - read with care.</b> "
|
||||||
|
"These loadings are each individually significant but "
|
||||||
|
"collectively explain little of the excess return; the "
|
||||||
|
"economically meaningful picture is a mostly-cash "
|
||||||
|
"vehicle with idiosyncratic alpha (the performance "
|
||||||
|
"table anchors to cash, not to this mix).</p>")
|
||||||
|
if not refs:
|
||||||
|
srow = search_row(sym)
|
||||||
|
a = srow.get("alpha_ann_5y")
|
||||||
|
return caveat + ("<p><b>Reference: cash (the T-bill rate itself)."
|
||||||
|
"</b> No "
|
||||||
|
"sleeve passed the forward-selection gates, so the fund's "
|
||||||
|
"excess returns are not explained by any benchmark mix - "
|
||||||
|
f"its entire excess performance is idiosyncratic (5y alpha "
|
||||||
|
f"{fmt_pct(a) if isinstance(a, (int, float)) else '—'}). "
|
||||||
|
"There is no meaningful 'beta' to this fund; it is a "
|
||||||
|
"standalone position.</p>")
|
||||||
|
sb = sum(c["beta"] for c in refs)
|
||||||
|
cash = 1 - sb
|
||||||
|
rows = []
|
||||||
|
for c in refs:
|
||||||
|
nm, desc = sleeve_desc(c["sym"])
|
||||||
|
rows.append(f"<tr><td><b>{c['sym'].upper()}</b> {c['beta']:+.2f}"
|
||||||
|
f"</td><td>{html.escape(nm)}</td>"
|
||||||
|
f"<td>{html.escape(desc)}</td></tr>")
|
||||||
|
cash_line = ""
|
||||||
|
if weak:
|
||||||
|
cash_line = caveat + cash_line
|
||||||
|
if cash > 0.05:
|
||||||
|
cash_line = (f"<p>The loadings sum to {sb:.2f}, i.e. the fund is "
|
||||||
|
f"~{cash:.0%} NET CASH (earns the T-bill rate; adds "
|
||||||
|
f"zero excess alpha).</p>")
|
||||||
|
elif cash < -0.05:
|
||||||
|
cash_line = (f"The loadings sum to {sb:.2f}, i.e. the fund is ~"
|
||||||
|
f"{-cash:.0%} NET LEVERED (borrows at ~the T-bill "
|
||||||
|
f"rate; that financing shows up as negative cash).</p>")
|
||||||
|
return ('<table><tr><th>loading</th><th>what it is</th>'
|
||||||
|
'<th>what it exposes you to</th></tr>' + "".join(rows)
|
||||||
|
+ "</table>" + cash_line
|
||||||
|
+ '<p class="small">The reference is NOT one index - it is '
|
||||||
|
'this fitted mix, rebuilt from the fund\'s own returns. '
|
||||||
|
'"Alpha" everywhere in this report means outperformance vs '
|
||||||
|
'this mix, in excess of the T-bill rate.</p>')
|
||||||
|
|
||||||
|
|
||||||
|
def tax_section(sym: str) -> str:
|
||||||
|
t = tax_row(sym)
|
||||||
|
if not t:
|
||||||
|
return "<p>No tax classification on file.</p>"
|
||||||
|
loc = t.get("location", "?")
|
||||||
|
basis = t.get("basis", "?")
|
||||||
|
conf = {"N-PORT": "from actual N-PORT holdings (high confidence)",
|
||||||
|
"sleeves": "from the return-sleeve mix (model, medium "
|
||||||
|
"confidence)"}.get(basis, basis)
|
||||||
|
notes = html.escape(t.get("notes") or "")
|
||||||
|
rec = {"TAXABLE": "Keep in the <b>taxable</b> account.",
|
||||||
|
"TAXABLE (munis)": "Keep in the <b>taxable</b> account - "
|
||||||
|
"tax-exempt interest is wasted in an IRA.",
|
||||||
|
"TAXABLE (defers to LTCG)": "Keep in the <b>taxable</b> "
|
||||||
|
"account - the income mostly "
|
||||||
|
"defers to the LTCG/ROC rate."}.get(
|
||||||
|
loc, f"Recommended account: <b>{html.escape(loc)}</b>.")
|
||||||
|
return (f"<p>Character score {t.get('score', '?')} "
|
||||||
|
f"({conf}). <b>Placement: {rec}</b></p>"
|
||||||
|
+ (f"<p class='small'>{notes}</p>" if notes else ""))
|
||||||
|
|
||||||
|
|
||||||
|
def cluster_section(sym: str, fr: dict, row: np.ndarray | None) -> str:
|
||||||
|
srow = search_row(sym)
|
||||||
|
if sym in MEMBER:
|
||||||
|
cid, clabel, cn = MEMBER[sym]
|
||||||
|
members = KMEANS["clusters"][cid]["syms"]
|
||||||
|
else:
|
||||||
|
if row is None:
|
||||||
|
return "<p>Not in the cluster scheme (no loading vector).</p>"
|
||||||
|
cid, clabel = cluster_of_row(row)
|
||||||
|
cn = KMEANS["clusters"].get(cid, {}).get("n", 0)
|
||||||
|
members = KMEANS["clusters"].get(cid, {}).get("syms", [])
|
||||||
|
peers = []
|
||||||
|
for s in members:
|
||||||
|
if s == sym:
|
||||||
|
continue
|
||||||
|
v = search_row(s)
|
||||||
|
if not isinstance(v.get("alpha_t_5y"), (int, float)):
|
||||||
|
continue
|
||||||
|
peers.append((v["alpha_t_5y"], v.get("r2_5y") or 0, s, v))
|
||||||
|
# best peers = highest POSITIVE alpha t (a fund with t = -5 is the
|
||||||
|
# cluster's worst, not a peer worth copying); top-4, positives first
|
||||||
|
peers.sort(key=lambda p: (p[0] > 0, p[0]), reverse=True)
|
||||||
|
pos = [p for p in peers if p[0] > 0]
|
||||||
|
peers = (pos + [p for p in peers if p[0] <= 0])[:4]
|
||||||
|
peers = [p[2] for p in peers]
|
||||||
|
if not peers:
|
||||||
|
return (f"<p>In cluster <b>{html.escape(clabel)}</b> (n={cn}) but "
|
||||||
|
"no peer with 5y alpha statistics.</p>")
|
||||||
|
rows = []
|
||||||
|
|
||||||
|
def statline(s: str) -> str:
|
||||||
|
p = price(s)
|
||||||
|
if p is None:
|
||||||
|
return ("—", "—", "—", "—", "—", "n/a")
|
||||||
|
st = perf_stats(p)
|
||||||
|
v = search_row(s)
|
||||||
|
t5 = window_ret(p, "2021-01-01", st["end"])
|
||||||
|
r2 = v.get("r2_5y")
|
||||||
|
a5 = v.get("alpha_ann_5y")
|
||||||
|
tt = v.get("alpha_t_5y")
|
||||||
|
tax = (tax_row(s) or {}).get("location") or "n/a"
|
||||||
|
return (fmt_pct(t5), fmt_pct(st["cagr"]), fmt_pct(st["mdd"]),
|
||||||
|
fmt_r2(r2),
|
||||||
|
(f"{fmt_pct(a5)} (t={tt:+.1f})"
|
||||||
|
if isinstance(a5, (int, float)) else "—"), tax)
|
||||||
|
|
||||||
|
p = price(sym)
|
||||||
|
st = perf_stats(p) if p is not None else {}
|
||||||
|
my = statline(sym)
|
||||||
|
rows.append(f"<tr class='me'><td><b>{sym.upper()} (this fund)</b></td>"
|
||||||
|
+ "".join(f"<td>{x}</td>" for x in my) + "</tr>")
|
||||||
|
for s in peers:
|
||||||
|
rows.append(f"<tr><td>{s.upper()} — "
|
||||||
|
f"{html.escape((search_row(s) or {}).get('name', '')[:40])}"
|
||||||
|
f"</td>" + "".join(f"<td>{x}</td>" for x in statline(s))
|
||||||
|
+ "</tr>")
|
||||||
|
tbl = ('<table><tr><th>fund</th><th>5y</th><th>CAGR</th>'
|
||||||
|
'<th>maxDD</th><th>R² 5y</th><th>alpha 5y</th><th>tax</th></tr>'
|
||||||
|
+ "".join(rows) + "</table>")
|
||||||
|
# advantages / disadvantages: computed deltas vs the peer set
|
||||||
|
adv, dis = [], []
|
||||||
|
if p is not None:
|
||||||
|
t5 = window_ret(p, "2021-01-01", st["end"])
|
||||||
|
vals = {}
|
||||||
|
for s in peers:
|
||||||
|
pp = price(s)
|
||||||
|
if pp is None:
|
||||||
|
continue
|
||||||
|
ss = perf_stats(pp)
|
||||||
|
vals[s] = (window_ret(pp, "2021-01-01", ss["end"]), ss["mdd"],
|
||||||
|
ss["vol"])
|
||||||
|
if vals:
|
||||||
|
best_t5 = max(v[0] for v in vals.values() if v[0] is not None)
|
||||||
|
best_dd = max(v[1] for v in vals.values())
|
||||||
|
low_vol = min(v[2] for v in vals.values())
|
||||||
|
if t5 is not None and t5 >= best_t5 - 0.02:
|
||||||
|
adv.append("5y return at the top of the cluster")
|
||||||
|
elif t5 is not None and t5 < best_t5 - 0.10:
|
||||||
|
dis.append(f"5y return trails the best peer by "
|
||||||
|
f"{100 * (best_t5 - t5):.0f}pp")
|
||||||
|
if st["mdd"] > best_dd + 0.05:
|
||||||
|
dis.append(f"deeper drawdown than the calmest peer "
|
||||||
|
f"({fmt_pct(st['mdd'])} vs {fmt_pct(best_dd)})")
|
||||||
|
elif st["mdd"] < best_dd - 0.05:
|
||||||
|
adv.append("sharpest drawdown in the cluster")
|
||||||
|
if st["vol"] < low_vol - 0.02:
|
||||||
|
adv.append("lowest volatility in the cluster")
|
||||||
|
elif st["vol"] > low_vol + 0.05:
|
||||||
|
dis.append("meaningfully more volatile than the "
|
||||||
|
"calmest peer")
|
||||||
|
txt = ""
|
||||||
|
if adv:
|
||||||
|
txt += "<p><b>Advantages vs peers:</b> " + "; ".join(adv) + ".</p>"
|
||||||
|
if dis:
|
||||||
|
txt += "<p><b>Disadvantages vs peers:</b> " + "; ".join(dis) + ".</p>"
|
||||||
|
if not txt:
|
||||||
|
txt = ("<p>The fund sits in the middle of its cluster - no "
|
||||||
|
"decisive edge on return, drawdown or volatility vs the "
|
||||||
|
"peers; the choice among them should come down to alpha "
|
||||||
|
"quality (t-stat), tax fit and the conviction in the "
|
||||||
|
"strategy.</p>")
|
||||||
|
return (f"<p>Cluster: <b>{html.escape(clabel)}</b> "
|
||||||
|
f"(n={cn}, k=30 grouping by return-driver signature).</p>"
|
||||||
|
+ tbl + txt)
|
||||||
|
|
||||||
|
|
||||||
|
def fund_loading_row(fr: dict) -> np.ndarray:
|
||||||
|
f = fr.get("full") or fr.get("rec5") or {}
|
||||||
|
betas = f.get("betas") or {}
|
||||||
|
row = np.array([betas.get(s, 0.0) or 0.0 for s in factors.DRIVERS],
|
||||||
|
dtype=float)
|
||||||
|
return np.append(row, 1.0 - row.sum())
|
||||||
|
|
||||||
|
|
||||||
|
def strategy_block(sym: str) -> str:
|
||||||
|
f = FONDS.get(sym)
|
||||||
|
if not f:
|
||||||
|
return ""
|
||||||
|
out = ""
|
||||||
|
if f.get("strategy"):
|
||||||
|
out += f"<details><summary>Strategy (excerpt from the filing)</summary>"
|
||||||
|
f"<p class='small'>{html.escape(f['strategy'])}</p></details>"
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def style_block(sym: str) -> str:
|
||||||
|
from fundlab import styletilt
|
||||||
|
prof = styletilt.style_profile(sym)
|
||||||
|
if not prof or not prof.get("full"):
|
||||||
|
return ""
|
||||||
|
f5 = {x["sym"]: x for x in (prof.get("rec5") or {}).get("factors", [])}
|
||||||
|
rows = []
|
||||||
|
for x in prof["full"]["factors"]:
|
||||||
|
y5 = f5.get(x["sym"], {})
|
||||||
|
if abs(x["t"]) < 2 and abs(y5.get("t", 0) or 0) < 2:
|
||||||
|
continue
|
||||||
|
rows.append(
|
||||||
|
f"<tr><td>{html.escape(x['name'])}</td>"
|
||||||
|
f"<td>{x['beta']:+.2f}</td><td>{x['t']:+.1f}</td>"
|
||||||
|
f"<td>{y5['beta']:+.2f}</td><td>{y5['t']:+.1f}</td>"
|
||||||
|
f"<td>{'✓' if x['sym'] in prof.get('identified', []) else ''}</td></tr>")
|
||||||
|
tbl = ('<table><tr><th>factor</th><th>β full</th><th>t full</th>'
|
||||||
|
'<th>β 5y</th><th>t 5y</th><th>identified</th></tr>'
|
||||||
|
+ "".join(rows) + "</table>")
|
||||||
|
para = "".join(f"<p>{html.escape(p)}</p>" for p in prof.get("commentary", []))
|
||||||
|
return ('<h4>Style tilts</h4>'
|
||||||
|
'<p class="small">22 style/asset sleeves regressed on the '
|
||||||
|
'excess returns of the fund (US funds proxy the global '
|
||||||
|
'factors); "identified" = survived the BIC forward-selection '
|
||||||
|
'gate on the full history.</p>' + tbl + para)
|
||||||
|
|
||||||
|
|
||||||
|
def narrative_block(sym: str) -> str:
|
||||||
|
from fundlab.narrative import narrate
|
||||||
|
return "".join(f"<p>{html.escape(par)}</p>" for par in narrate(sym))
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------ build
|
||||||
|
def fund_section(sym: str, title: str, subtitle: str) -> str:
|
||||||
|
fr = factor_row(sym)
|
||||||
|
dr = decomp_row(sym)
|
||||||
|
srow = search_row(sym)
|
||||||
|
name = (srow.get("name") or (FONDS.get(sym) or {}).get("name")
|
||||||
|
or (fr or {}).get("name") or sym.upper())
|
||||||
|
refs = ref_components(sym, fr)
|
||||||
|
load = fund_loading_row(fr) if fr else None
|
||||||
|
# weak-fit (idiosyncratic) funds: the forward-selected mix is a
|
||||||
|
# statistically-thin spec combination (offsetting VIX/duration legs);
|
||||||
|
# anchoring the table to it misleads (a "reference" that loses 79% in
|
||||||
|
# 2022 for a fund that lost 2.4%). Below the fit gate the honest
|
||||||
|
# reference is CASH - the fund IS ~net-cash + idiosyncratic alpha.
|
||||||
|
r25 = srow.get("r2_5y") if isinstance(srow.get("r2_5y"),
|
||||||
|
(int, float)) else None
|
||||||
|
r2f = (fr.get("rec5") or fr.get("full") or {}).get("r2")
|
||||||
|
fit = r25 if r25 is not None else r2f
|
||||||
|
refs_curve = refs if (fit is not None and fit >= 0.5) else []
|
||||||
|
return f"""
|
||||||
|
<h3 id="{sym}">{html.escape(title)}
|
||||||
|
<span class="sub">{html.escape(subtitle)}</span></h3>
|
||||||
|
<div class="fund">{strategy_block(sym)}
|
||||||
|
<h4>Discussion</h4>
|
||||||
|
{narrative_block(sym)}
|
||||||
|
{equity_figure(sym, name, refs_curve)}
|
||||||
|
<h4>Performance</h4>
|
||||||
|
{perf_table(price(sym), refs_curve) if price(sym) is not None else '<p>no price data</p>'}
|
||||||
|
<h4>What drove the returns</h4>
|
||||||
|
{drivers_section(fr, dr, srow)}
|
||||||
|
{style_block(sym)}
|
||||||
|
<h4>The reference mix - and what it exposes you to</h4>
|
||||||
|
{reference_section(refs, refs_curve, sym)}
|
||||||
|
<h4>Tax character & placement</h4>
|
||||||
|
{tax_section(sym)}
|
||||||
|
<h4>Peer comparison (same return-driver cluster)</h4>
|
||||||
|
{cluster_section(sym, fr, load)}
|
||||||
|
</div>"""
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
t0 = time.time()
|
||||||
|
load_plotly()
|
||||||
|
print("building report ...", flush=True)
|
||||||
|
|
||||||
|
cand = [v for v in SEARCH.values()
|
||||||
|
if isinstance(v, dict)
|
||||||
|
and str(v.get("verdict", "")).startswith("CANDIDATE")]
|
||||||
|
cand.sort(key=lambda v: -(v.get("alpha_t_5y")
|
||||||
|
if isinstance(v.get("alpha_t_5y"),
|
||||||
|
(int, float)) else -9))
|
||||||
|
|
||||||
|
# shortlist: the 16 actively-managed funds (3 are share classes of
|
||||||
|
# the same fund: pmfkx=pmaix, lcrix=lcorx, egrsx=eagmx)
|
||||||
|
from fundlab.decompose import ALIAS
|
||||||
|
from fundlab.nport import FUND_TOKENS
|
||||||
|
short = [s for s in FUND_TOKENS if s not in ALIAS]
|
||||||
|
|
||||||
|
toc = []
|
||||||
|
body = []
|
||||||
|
for i, v in enumerate(cand, 1):
|
||||||
|
s = v["sym"]
|
||||||
|
toc.append(f'<li><a href="#{s}">{s.upper()}</a> — '
|
||||||
|
f'{html.escape((v.get("name") or "")[:48])}</li>')
|
||||||
|
body.append(fund_section(
|
||||||
|
s, f"C{i:02d} · {s.upper()}",
|
||||||
|
f"{v.get('name', '')} — {str(v.get('verdict', ''))[:60]}"))
|
||||||
|
for i, s in enumerate(short, 1):
|
||||||
|
nm = (FONDS.get(s) or {}).get("name", s.upper())
|
||||||
|
toc.append(f'<li><a href="#{s}">S{i:02d} · {s.upper()}</a> — '
|
||||||
|
f'{html.escape(nm[:48])}</li>')
|
||||||
|
body.append(fund_section(s, f"S{i:02d} · {s.upper()}", nm))
|
||||||
|
|
||||||
|
doc = f"""<!DOCTYPE html>
|
||||||
|
<html><head><meta charset="utf-8">
|
||||||
|
<title>Fund report - candidates & shortlist</title>
|
||||||
|
<style>
|
||||||
|
body {{ font-family: -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif;
|
||||||
|
margin: 0; color: #1a1a2e; background: #fafafa; }}
|
||||||
|
.wrap {{ display: flex; }}
|
||||||
|
nav {{ width: 270px; min-width: 270px; position: sticky; top: 0;
|
||||||
|
height: 100vh; overflow-y: auto; background: #fff;
|
||||||
|
border-right: 1px solid #ddd; padding: 16px; box-sizing: border-box; }}
|
||||||
|
main {{ flex: 1; padding: 24px 36px; max-width: 1150px; }}
|
||||||
|
h1 {{ font-size: 26px; }} h3 {{ border-top: 3px solid #1a1a2e;
|
||||||
|
padding-top: 18px; margin-top: 40px; }}
|
||||||
|
h3 .sub {{ font-weight: normal; font-size: 14px; color: #555;
|
||||||
|
display: block; margin-top: 4px; }}
|
||||||
|
h4 {{ margin: 18px 0 6px; font-size: 15px; }}
|
||||||
|
table {{ border-collapse: collapse; margin: 8px 0 14px; font-size: 13px; }}
|
||||||
|
th, td {{ border: 1px solid #ccc; padding: 4px 9px; text-align: left; }}
|
||||||
|
th {{ background: #eee; }}
|
||||||
|
tr.me td {{ background: #fff8e1; }}
|
||||||
|
.small {{ color: #555; font-size: 12.5px; }}
|
||||||
|
nav a {{ text-decoration: none; color: #1a1a2e; font-size: 13px;
|
||||||
|
display: block; padding: 3px 0; }}
|
||||||
|
nav a:hover {{ color: #b00020; }}
|
||||||
|
nav h2 {{ font-size: 14px; margin: 14px 0 6px; }}
|
||||||
|
details {{ margin: 6px 0; }} summary {{ cursor: pointer;
|
||||||
|
font-size: 13px; color: #333; }}
|
||||||
|
</style>
|
||||||
|
{"<script>" + PLOTLY_JS + "</script>" if PLOTLY_JS else
|
||||||
|
'<script src="https://cdn.plot.ly/plotly-2.35.2.min.js"></script>'}
|
||||||
|
</head><body><div class="wrap">
|
||||||
|
<nav>
|
||||||
|
<b>Return-driver report</b><br><span class="small">generated
|
||||||
|
{time.strftime('%Y-%m-%d %H:%M')}</span>
|
||||||
|
<h2>Candidates (alpha screen, excess of T-bill)</h2>
|
||||||
|
<ol>{''.join(toc[:len(cand)])}</ol>
|
||||||
|
<h2>Shortlist (your funds)</h2>
|
||||||
|
<ol start="{len(cand) + 1}">{''.join(toc[len(cand):])}</ol>
|
||||||
|
</nav>
|
||||||
|
<main>
|
||||||
|
<h1>Fund report - {len(cand)} alpha candidates & {len(short)}
|
||||||
|
shortlist funds</h1>
|
||||||
|
<p class="small"><b>Method.</b> Every alpha in this report is computed
|
||||||
|
<b>in excess of the 3-month T-bill rate</b> (BIL total return as the
|
||||||
|
local risk-free series): the fund's daily total returns are regressed on
|
||||||
|
sleeve benchmarks that are netted against the same rate, so a cash
|
||||||
|
position contributes exactly zero. "Reference" is never one index - it
|
||||||
|
is each fund's <b>own fitted sleeve mix</b> (BIC forward selection on the
|
||||||
|
broad axes, or the full 34-sleeve OLS for the loadings). R² measures how
|
||||||
|
much of the excess return the mix explains; alpha is what is left.
|
||||||
|
"Net cash" = 1 − (sum of loadings). Equity curves are total-return
|
||||||
|
(Adj Close) over the maximum local history, rebased to 100.</p>
|
||||||
|
{''.join(body)}
|
||||||
|
<p class="small" style="margin-top:40px">Generated by fundlab.report -
|
||||||
|
data as of {time.strftime('%Y-%m-%d')}. Local price histories may lag a
|
||||||
|
day or two. Cluster = k=30 k-means on the excess-return loading vectors
|
||||||
|
(34 sleeves + net-cash axis).</p>
|
||||||
|
</main></div></body></html>"""
|
||||||
|
OUT.write_text(doc)
|
||||||
|
print(f"wrote {OUT} in {time.time() - t0:.0f}s "
|
||||||
|
f"({len(doc) / 1e6:.1f} MB)")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
400
fundlab/reportdata.py
Normal file
400
fundlab/reportdata.py
Normal file
|
|
@ -0,0 +1,400 @@
|
||||||
|
"""Build reports/report_data.json: everything the web app (and the HTML
|
||||||
|
report) need for the per-fund report pages, in one structured file.
|
||||||
|
|
||||||
|
One entry per fund (11 alpha candidates + 13 shortlist funds):
|
||||||
|
meta name, verdict, group, order
|
||||||
|
narrative list of prose paragraphs (fundlab.narrative)
|
||||||
|
chart {dates, fund, ref, ivv} (downsampled price paths, rebased)
|
||||||
|
perf rows [period, fund, reference, ivv, fund-ref] (strings)
|
||||||
|
drivers markdown lines (reference model, signature, verdicts)
|
||||||
|
reference {rows [[loading, name, exposure]], weak, netcash, text}
|
||||||
|
tax plain text
|
||||||
|
peers {cluster, rows, proscons}
|
||||||
|
|
||||||
|
Run: .venv/bin/python -m fundlab.reportdata
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
from fundlab import report as _r
|
||||||
|
from fundlab import decompose
|
||||||
|
from fundlab import styletilt
|
||||||
|
from fundlab.narrative import narrate
|
||||||
|
|
||||||
|
HERE = Path(__file__).parent
|
||||||
|
OUT = HERE.parent / "reports" / "report_data.json"
|
||||||
|
|
||||||
|
MAX_PTS = 1500
|
||||||
|
|
||||||
|
|
||||||
|
def _down(s: pd.Series) -> tuple[list, list]:
|
||||||
|
if s is None:
|
||||||
|
return [], []
|
||||||
|
if len(s) > MAX_PTS:
|
||||||
|
s = s.iloc[:: (len(s) // MAX_PTS + 1)]
|
||||||
|
return [str(d.date()) for d in s.index], [float(v) for v in s]
|
||||||
|
|
||||||
|
|
||||||
|
def _chart(sym: str, refs_curve: list[dict]) -> dict:
|
||||||
|
p = _r.price(sym)
|
||||||
|
fd, fv = _down(100 * p / p.iloc[0] if p is not None else None)
|
||||||
|
if refs_curve:
|
||||||
|
mix = _r.mix_series(refs_curve)
|
||||||
|
else:
|
||||||
|
b = _r.price("bil")
|
||||||
|
mix = 100 * b / b.iloc[0] if b is not None else None
|
||||||
|
md, mv = _down(mix)
|
||||||
|
iv = _r.price("ivv")
|
||||||
|
id_, ivv = _down(100 * iv / iv.iloc[0] if iv is not None else None)
|
||||||
|
return {"dates": fd, "fund": fv, "ref_dates": md, "ref": mv,
|
||||||
|
"ivv_dates": id_, "ivv": ivv}
|
||||||
|
|
||||||
|
|
||||||
|
def _perf_rows(sym: str, refs_curve: list[dict]) -> list[list[str]]:
|
||||||
|
p = _r.price(sym)
|
||||||
|
if p is None:
|
||||||
|
return []
|
||||||
|
mix = (_r.mix_series(refs_curve) if refs_curve
|
||||||
|
else _r.price("bil"))
|
||||||
|
iv = _r.price("ivv")
|
||||||
|
st = _r.perf_stats(p)
|
||||||
|
rows = []
|
||||||
|
|
||||||
|
def add(label, a, b):
|
||||||
|
fr_ = _r.window_ret(p, a, b)
|
||||||
|
mr = _r.window_ret(mix, a, b)
|
||||||
|
ir = _r.window_ret(iv, a, b)
|
||||||
|
gap = (fr_ - mr) if (fr_ is not None and mr is not None) else None
|
||||||
|
rows.append([label, _r.fmt_pct(fr_), _r.fmt_pct(mr),
|
||||||
|
_r.fmt_pct(ir), _r.fmt_pct(gap)])
|
||||||
|
|
||||||
|
add("Full history", st["start"], st["end"])
|
||||||
|
add("Last 5y", "2021-01-01", st["end"])
|
||||||
|
add("Last 1y", "2025-09-01", st["end"])
|
||||||
|
for lab, a, b in _r.EPISODES:
|
||||||
|
add(lab, a, b)
|
||||||
|
yr = p.resample("YE").last().dropna()
|
||||||
|
years = [str(yr.index[i].year) for i in range(1, len(yr))][-6:]
|
||||||
|
for i, y in enumerate(years):
|
||||||
|
a = f"{y}-01-01"
|
||||||
|
b = f"{int(y) + 1}-01-01" if i < len(years) - 1 else st["end"]
|
||||||
|
add(y, a, b)
|
||||||
|
return rows
|
||||||
|
|
||||||
|
|
||||||
|
def _drivers(sym: str, fr: dict, srow: dict, dr: dict) -> list[str]:
|
||||||
|
out = []
|
||||||
|
a5 = srow.get("alpha_ann_5y")
|
||||||
|
t5 = srow.get("alpha_t_5y")
|
||||||
|
r25 = srow.get("r2_5y")
|
||||||
|
if isinstance(r25, (int, float)) or isinstance(a5, (int, float)):
|
||||||
|
out.append(
|
||||||
|
f"**Reference model, last 5 years:** R² = "
|
||||||
|
f"{_r.fmt_r2(r25 if isinstance(r25, (int, float)) else None)}, "
|
||||||
|
f"alpha = "
|
||||||
|
f"{_r.fmt_pct(a5) if isinstance(a5, (int, float)) else '—'}"
|
||||||
|
f"{' (t = ' + format(t5, '+.1f') + ')' if isinstance(t5, (int, float)) else ''}")
|
||||||
|
a_f = (fr.get("full") or {}).get("alpha_ann")
|
||||||
|
t_f = (fr.get("full") or {}).get("alpha_t")
|
||||||
|
r2f = srow.get("r2_full")
|
||||||
|
if isinstance(r2f, (int, float)) or isinstance(a_f, (int, float)):
|
||||||
|
out.append(
|
||||||
|
f"**Reference model, full history:** R² = "
|
||||||
|
f"{_r.fmt_r2(r2f if isinstance(r2f, (int, float)) else None)}, "
|
||||||
|
f"alpha = "
|
||||||
|
f"{_r.fmt_pct(a_f) if isinstance(a_f, (int, float)) else '—'}"
|
||||||
|
f"{' (t = ' + format(t_f, '+.1f') + ')' if isinstance(t_f, (int, float)) else ''}.")
|
||||||
|
f = fr.get("rec5") or {}
|
||||||
|
betas = f.get("betas") or {}
|
||||||
|
top = sorted(betas.items(), key=lambda kv: -abs(kv[1]))[:6]
|
||||||
|
if top:
|
||||||
|
out.append("**Return-driver signature (34 sleeves):** "
|
||||||
|
+ ", ".join(f"`{s}` {b:+.2f}" for s, b in top)
|
||||||
|
+ f" - net cash {1 - sum(betas.values()):+.2f}.")
|
||||||
|
if dr and "verdict" in dr:
|
||||||
|
out.append(f"**Decomposition verdict:** {dr['verdict']}")
|
||||||
|
roll = dr.get("rolling") or {}
|
||||||
|
if roll.get("max_drift") is not None:
|
||||||
|
out.append(f"Weight stability: max 1y β-drift = "
|
||||||
|
f"{roll['max_drift']:.2f} (0 = perfectly stable, "
|
||||||
|
f">1 = unstable).")
|
||||||
|
if dr.get("note"):
|
||||||
|
out.append(f"*{dr['note']}*")
|
||||||
|
if srow.get("verdict"):
|
||||||
|
out.append(f"**Screen verdict:** {srow['verdict']}")
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def _reference(sym: str, fr: dict, refs: list[dict],
|
||||||
|
refs_curve: list[dict]) -> dict:
|
||||||
|
rows = []
|
||||||
|
for c in refs:
|
||||||
|
nm, desc = _r.sleeve_desc(c["sym"])
|
||||||
|
rows.append([f"{c['sym'].upper()} {c['beta']:+.2f}", nm, desc])
|
||||||
|
sb = sum(c["beta"] for c in refs)
|
||||||
|
cash = 1 - sb
|
||||||
|
if cash > 0.05:
|
||||||
|
net = f"loadings sum to {sb:.2f} → ~{cash:.0%} net cash"
|
||||||
|
elif cash < -0.05:
|
||||||
|
net = f"loadings sum to {sb:.2f} → ~{-cash:.0%} net levered"
|
||||||
|
else:
|
||||||
|
net = f"loadings sum to {sb:.2f} → fully invested"
|
||||||
|
weak = bool(refs) and not refs_curve
|
||||||
|
text = ("**Weak fit - read with care.** These loadings are each "
|
||||||
|
"individually significant but collectively explain little; "
|
||||||
|
"the performance table anchors to cash, not this mix."
|
||||||
|
if weak else
|
||||||
|
"The reference is the fund's own fitted sleeve mix; "
|
||||||
|
"'alpha' everywhere means outperformance vs this mix, in "
|
||||||
|
"excess of the T-bill rate.")
|
||||||
|
return {"rows": rows, "weak": weak, "netcash": net, "text": text}
|
||||||
|
|
||||||
|
|
||||||
|
def _tax(sym: str) -> str:
|
||||||
|
t = _r.tax_row(sym)
|
||||||
|
if not t:
|
||||||
|
return "No tax classification on file."
|
||||||
|
loc = t.get("location", "?")
|
||||||
|
basis = t.get("basis", "?")
|
||||||
|
conf = "from actual N-PORT holdings (high confidence)" \
|
||||||
|
if basis == "N-PORT" else "from the return-sleeve mix (model)"
|
||||||
|
s = (f"Character score {t.get('score', '?')} ({conf}). ")
|
||||||
|
if "MIXED" in loc:
|
||||||
|
s += "Model says MIXED - the last 1099-DIV is the arbiter."
|
||||||
|
elif "TAXABLE" in loc:
|
||||||
|
if "munis" in loc:
|
||||||
|
s += ("Keep in the **taxable** account "
|
||||||
|
"(munis - tax-exempt interest is wasted in an IRA).")
|
||||||
|
elif "defers" in loc:
|
||||||
|
s += ("Keep in the **taxable** account "
|
||||||
|
"(income mostly defers to the LTCG/ROC rate).")
|
||||||
|
else:
|
||||||
|
s += "Keep in the **taxable** account."
|
||||||
|
else:
|
||||||
|
s += f"Recommended account: **{loc}**."
|
||||||
|
if t.get("notes"):
|
||||||
|
s += f" _{t['notes']}_"
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def _peers(sym: str, fr: dict) -> dict:
|
||||||
|
# no return history: a zero loading vector would park the fund in the
|
||||||
|
# cash cluster - no peer table for a fund with no measured returns
|
||||||
|
if _r.price(sym) is None:
|
||||||
|
return {}
|
||||||
|
if sym in _r.MEMBER:
|
||||||
|
cid, clabel, cn = _r.MEMBER[sym]
|
||||||
|
members = _r.KMEANS["clusters"][cid]["syms"]
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
cid, clabel = _r.cluster_of_row(_r.fund_loading_row(fr))
|
||||||
|
except Exception:
|
||||||
|
return {}
|
||||||
|
cn = _r.KMEANS["clusters"].get(cid, {}).get("n", 0)
|
||||||
|
members = _r.KMEANS["clusters"].get(cid, {}).get("syms", [])
|
||||||
|
peers = []
|
||||||
|
for s in members:
|
||||||
|
if s == sym:
|
||||||
|
continue
|
||||||
|
v = _r.search_row(s)
|
||||||
|
if isinstance(v.get("alpha_t_5y"), (int, float)):
|
||||||
|
peers.append((v["alpha_t_5y"], s))
|
||||||
|
peers.sort(key=lambda x: (x[0] > 0, x[0]), reverse=True)
|
||||||
|
pos = [p for p in peers if p[0] > 0]
|
||||||
|
peers = [s for _t, s in (pos + [p for p in peers if p[0] <= 0])[:4]]
|
||||||
|
|
||||||
|
def statline(s: str) -> list[str]:
|
||||||
|
p = _r.price(s)
|
||||||
|
if p is None:
|
||||||
|
return ["—", "—", "—", "—", "—", "n/a"]
|
||||||
|
st = _r.perf_stats(p)
|
||||||
|
v = _r.search_row(s)
|
||||||
|
t5 = _r.window_ret(p, "2021-01-01", st["end"])
|
||||||
|
a5 = v.get("alpha_ann_5y")
|
||||||
|
tt = v.get("alpha_t_5y")
|
||||||
|
tax = (_r.tax_row(s) or {}).get("location") or "n/a"
|
||||||
|
return [_r.fmt_pct(t5), _r.fmt_pct(st["cagr"]),
|
||||||
|
_r.fmt_pct(st["mdd"]),
|
||||||
|
_r.fmt_r2(v.get("r2_5y")),
|
||||||
|
(f"{_r.fmt_pct(a5)} (t={tt:+.1f})"
|
||||||
|
if isinstance(a5, (int, float)) else "—"), tax]
|
||||||
|
|
||||||
|
rows = [[f"{sym.upper()} (this fund)", *statline(sym)]]
|
||||||
|
for s in peers:
|
||||||
|
rows.append([s.upper(), *statline(s)])
|
||||||
|
|
||||||
|
# pros / cons
|
||||||
|
adv, dis = [], []
|
||||||
|
p = _r.price(sym)
|
||||||
|
if p is not None and peers:
|
||||||
|
st = _r.perf_stats(p)
|
||||||
|
t5 = _r.window_ret(p, "2021-01-01", st["end"])
|
||||||
|
vals = {}
|
||||||
|
for s in peers:
|
||||||
|
pp = _r.price(s)
|
||||||
|
if pp is None:
|
||||||
|
continue
|
||||||
|
ss = _r.perf_stats(pp)
|
||||||
|
vals[s] = (_r.window_ret(pp, "2021-01-01", ss["end"]),
|
||||||
|
ss["mdd"], ss["vol"])
|
||||||
|
if vals:
|
||||||
|
best_t5 = max(v[0] for v in vals.values() if v[0] is not None)
|
||||||
|
best_dd = max(v[1] for v in vals.values())
|
||||||
|
low_vol = min(v[2] for v in vals.values())
|
||||||
|
if t5 is not None and t5 >= best_t5 - 0.02:
|
||||||
|
adv.append("5y return at the top of the cluster")
|
||||||
|
elif t5 is not None and t5 < best_t5 - 0.10:
|
||||||
|
dis.append(f"5y return trails the best peer by "
|
||||||
|
f"{100 * (best_t5 - t5):.0f}pp")
|
||||||
|
if st["mdd"] < best_dd - 0.05:
|
||||||
|
adv.append("sharpest drawdown in the cluster")
|
||||||
|
elif st["mdd"] > best_dd + 0.05:
|
||||||
|
dis.append(f"deeper drawdown than the calmest peer "
|
||||||
|
f"({_r.fmt_pct(st['mdd'])} vs "
|
||||||
|
f"{_r.fmt_pct(best_dd)})")
|
||||||
|
if st["vol"] < low_vol - 0.02:
|
||||||
|
adv.append("lowest volatility in the cluster")
|
||||||
|
elif st["vol"] > low_vol + 0.05:
|
||||||
|
dis.append("meaningfully more volatile than the "
|
||||||
|
"calmest peer")
|
||||||
|
if adv:
|
||||||
|
pc = "**Advantages vs peers:** " + "; ".join(adv) + "."
|
||||||
|
elif dis:
|
||||||
|
pc = "**Disadvantages vs peers:** " + "; ".join(dis) + "."
|
||||||
|
else:
|
||||||
|
pc = ("Middle of the cluster - no decisive edge on return, "
|
||||||
|
"drawdown or volatility; the choice comes down to alpha "
|
||||||
|
"quality (t), tax fit and conviction in the strategy.")
|
||||||
|
if dis and adv:
|
||||||
|
pc += " **Disadvantages:** " + "; ".join(dis) + "."
|
||||||
|
return {"cluster": clabel, "n": cn,
|
||||||
|
"rows": rows, "proscons": pc}
|
||||||
|
|
||||||
|
|
||||||
|
ADHOC_FILE = HERE.parent / "reports" / "report_data_adhoc.json"
|
||||||
|
_ADHOC_MEM: dict = None # lazy-loaded disk cache
|
||||||
|
|
||||||
|
|
||||||
|
def _adhoc_store() -> dict:
|
||||||
|
global _ADHOC_MEM
|
||||||
|
if _ADHOC_MEM is None:
|
||||||
|
try:
|
||||||
|
_ADHOC_MEM = json.loads(ADHOC_FILE.read_text())
|
||||||
|
except Exception:
|
||||||
|
_ADHOC_MEM = {"funds": {}}
|
||||||
|
return _ADHOC_MEM
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_adhoc(syms: list[str]) -> dict[str, dict]:
|
||||||
|
"""Build report entries for ARBITRARY funds (any symbol the user puts
|
||||||
|
in the portfolio box), cached in memory + on disk so repeat loads are
|
||||||
|
instant and survive server restarts. The one-time ~30-60 s driver-panel
|
||||||
|
build happens on the first call in a fresh process."""
|
||||||
|
store = _adhoc_store()
|
||||||
|
funds = store["funds"]
|
||||||
|
missing = [s for s in syms
|
||||||
|
if s not in funds
|
||||||
|
and _r.price(s) is not None]
|
||||||
|
if missing:
|
||||||
|
for s in missing:
|
||||||
|
funds[s] = build_fund(s, "adhoc",
|
||||||
|
order=len(funds) + 1)
|
||||||
|
ADHOC_FILE.parent.mkdir(exist_ok=True)
|
||||||
|
ADHOC_FILE.write_text(json.dumps(store))
|
||||||
|
return {s: funds[s] for s in syms if s in funds}
|
||||||
|
|
||||||
|
|
||||||
|
def build_fund(sym: str, group: str, order: int) -> dict:
|
||||||
|
t0 = time.time()
|
||||||
|
fr = _r.factor_row(sym)
|
||||||
|
dr = _r.decomp_row(sym)
|
||||||
|
srow = _r.search_row(sym)
|
||||||
|
name = (srow.get("name") or _r.FONDS.get(sym, {}).get("name")
|
||||||
|
or (fr or {}).get("name") or sym.upper())
|
||||||
|
refs = _r.ref_components(sym, fr)
|
||||||
|
r2f_ = (fr.get("rec5") or fr.get("full") or {}).get("r2")
|
||||||
|
r25 = srow.get("r2_5y") if isinstance(srow.get("r2_5y"), (int, float)) \
|
||||||
|
else None
|
||||||
|
fit = r25 if r25 is not None else r2f_
|
||||||
|
refs_curve = refs if (fit is not None and fit >= 0.5) else []
|
||||||
|
p = _r.price(sym)
|
||||||
|
st_ = _r.perf_stats(p) if p is not None else {}
|
||||||
|
stats = {"t5y": _r.fmt_pct(_r.window_ret(p, "2021-01-01",
|
||||||
|
st_["end"])) if p is not None
|
||||||
|
else "—",
|
||||||
|
"cagr": _r.fmt_pct(st_.get("cagr")),
|
||||||
|
"mdd": _r.fmt_pct(st_.get("mdd")),
|
||||||
|
"r2_5y": _r.fmt_r2(srow.get("r2_5y")),
|
||||||
|
"alpha_5y": (f"{_r.fmt_pct(srow['alpha_ann_5y'])} "
|
||||||
|
f"(t={srow['alpha_t_5y']:+.1f})"
|
||||||
|
if isinstance(srow.get("alpha_ann_5y"),
|
||||||
|
(int, float)) else "—")}
|
||||||
|
d = {
|
||||||
|
"meta": {"sym": sym, "name": name, "group": group, "order": order,
|
||||||
|
"verdict": srow.get("verdict", ""),
|
||||||
|
"objective": (_r.FONDS.get(sym) or {}).get("objective",
|
||||||
|
"")},
|
||||||
|
"stats": stats,
|
||||||
|
"narrative": narrate(sym),
|
||||||
|
"chart": _chart(sym, refs_curve),
|
||||||
|
"perf": _perf_rows(sym, refs_curve),
|
||||||
|
"drivers": _drivers(sym, fr, srow, dr),
|
||||||
|
"reference": _reference(sym, fr, refs, refs_curve),
|
||||||
|
"tax": _tax(sym),
|
||||||
|
"peers": _peers(sym, fr),
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
d["style"] = styletilt.style_profile(sym)
|
||||||
|
except Exception:
|
||||||
|
d["style"] = None
|
||||||
|
print(f" {sym:8s} {time.time() - t0:5.1f}s", flush=True)
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
from fundlab.decompose import ALIAS
|
||||||
|
from fundlab.nport import FUND_TOKENS
|
||||||
|
t0 = time.time()
|
||||||
|
cand = [v["sym"] for v in _r.SEARCH.values()
|
||||||
|
if isinstance(v, dict)
|
||||||
|
and str(v.get("verdict", "")).startswith("CANDIDATE")]
|
||||||
|
cand.sort(key=lambda s: -(_r.SEARCH[s]["alpha_t_5y"]
|
||||||
|
if isinstance(_r.SEARCH[s].get("alpha_t_5y"),
|
||||||
|
(int, float)) else -9))
|
||||||
|
short = [s for s in FUND_TOKENS if s not in ALIAS]
|
||||||
|
data = {"generated": time.strftime("%Y-%m-%d %H:%M"),
|
||||||
|
"funds": {}}
|
||||||
|
i = 0
|
||||||
|
for s in cand:
|
||||||
|
i += 1
|
||||||
|
data["funds"][s] = build_fund(s, "candidate", i)
|
||||||
|
for s in short:
|
||||||
|
i += 1
|
||||||
|
data["funds"][s] = build_fund(s, "shortlist", i)
|
||||||
|
OUT.parent.mkdir(exist_ok=True)
|
||||||
|
OUT.write_text(json.dumps(data))
|
||||||
|
# rebuild any on-demand (Symbol-box) reports so they gain the new
|
||||||
|
# sections too; keep their "adhoc" group
|
||||||
|
if ADHOC_FILE.exists():
|
||||||
|
try:
|
||||||
|
_old = json.loads(ADHOC_FILE.read_text())["funds"]
|
||||||
|
except Exception:
|
||||||
|
_old = {}
|
||||||
|
for j, s in enumerate(_old, 1):
|
||||||
|
if s in cand or s in short:
|
||||||
|
continue
|
||||||
|
_old[s] = build_fund(s, "adhoc", order=-j)
|
||||||
|
ADHOC_FILE.write_text(json.dumps({"funds": _old}))
|
||||||
|
print(f"rebuilt {len(_old)} ad-hoc reports")
|
||||||
|
print(f"wrote {OUT} in {time.time() - t0:.0f}s "
|
||||||
|
f"({OUT.stat().st_size / 1e6:.1f} MB, {len(data['funds'])} funds)")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
47683
fundlab/search_all.json
47683
fundlab/search_all.json
File diff suppressed because one or more lines are too long
1
fundlab/search_all_rawalpha.json
Normal file
1
fundlab/search_all_rawalpha.json
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -1,2 +1,4 @@
|
||||||
2026-08-28 14:52:00
|
2026-08-28 14:52:00
|
||||||
server_watchdog: no answer on :8599 - relaunching
|
server_watchdog: no answer on :8599 - relaunching
|
||||||
|
2026-08-30 13:26:18
|
||||||
|
server_watchdog: no answer on :8599 - relaunching
|
||||||
|
|
|
||||||
257
fundlab/styletilt.py
Normal file
257
fundlab/styletilt.py
Normal file
|
|
@ -0,0 +1,257 @@
|
||||||
|
"""Style-tilt battery: mathematical factor identification for one fund.
|
||||||
|
|
||||||
|
Regresses the fund's daily excess-of-T-bill returns on a battery of 22
|
||||||
|
style/asset sleeves (US funds proxying the global style factors; a fund
|
||||||
|
expresses them in its own universe, so betas are the right sign and
|
||||||
|
magnitude but approximate), over the full history and the last 5 years:
|
||||||
|
|
||||||
|
* plain OLS -> every factor's beta + t-stat (exploratory view)
|
||||||
|
* BIC forward selection -> the IDENTIFIED tilt stack (the strict gate:
|
||||||
|
a factor is only in if it measurably improves the model)
|
||||||
|
* residual alpha after the identified stack -> "is there skill left?"
|
||||||
|
|
||||||
|
Plus data-driven English commentary (fundlab.styletilt.commentary).
|
||||||
|
|
||||||
|
Caveats stated in the commentary, not hidden: US sleeves proxy global
|
||||||
|
factors; style sleeves are mutually collinear, so single-OLS t-stats are
|
||||||
|
indicative and the BIC set is the identification.
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
from fundlab import decompose
|
||||||
|
|
||||||
|
# factor label -> sleeve ticker (US proxies for the global factors)
|
||||||
|
BATTERY: dict[str, str] = {
|
||||||
|
"int-dev (EFA)": "efa", "EM (VWO)": "vwo", "growth (VUG)": "vug",
|
||||||
|
"value (VTV)": "vtv", "small (IWM)": "iwm", "equalwt (RSP)": "rsp",
|
||||||
|
"lowvol (USMV)": "usmv", "lowvol (DFLVX)": "dflvx",
|
||||||
|
"quality (QUAL)": "qual", "momentum (MTUM)": "mtum",
|
||||||
|
"dividend (HDV)": "hdv", "div-apprec (VYM)": "vym",
|
||||||
|
"longdur (TLT)": "tlt", "gold (GLD)": "gld",
|
||||||
|
"EUR (FXE)": "fxe", "JPY (FXY)": "fxy", "AUD (FXU)": "fxu",
|
||||||
|
"utilities (XLU)": "xlu", "staples (XLP)": "xlp",
|
||||||
|
"health (XLV)": "xlv", "banks (XLF)": "xlf", "energy (XLE)": "xle",
|
||||||
|
}
|
||||||
|
SYMS = list(dict.fromkeys(BATTERY.values()))
|
||||||
|
INV = {v: k for k, v in BATTERY.items()}
|
||||||
|
|
||||||
|
_PANEL: pd.DataFrame | None = None
|
||||||
|
|
||||||
|
|
||||||
|
def _panel() -> pd.DataFrame:
|
||||||
|
"""Battery sleeves' daily EXCESS-of-T-bill returns, cached per process."""
|
||||||
|
global _PANEL
|
||||||
|
if _PANEL is None:
|
||||||
|
_PANEL = decompose.excess(
|
||||||
|
decompose.returns_panel(SYMS, start=decompose.FULL_WINDOW))
|
||||||
|
return _PANEL
|
||||||
|
|
||||||
|
|
||||||
|
def _fund_excess(sym: str) -> pd.Series:
|
||||||
|
p = decompose.adj_close(sym)
|
||||||
|
if p is None:
|
||||||
|
return pd.Series(dtype=float)
|
||||||
|
y = p.pct_change()
|
||||||
|
rf = decompose.rf_series()
|
||||||
|
if rf is not None:
|
||||||
|
y = y.sub(rf.reindex(y.index).fillna(0.0))
|
||||||
|
return y
|
||||||
|
|
||||||
|
|
||||||
|
def _fit(y: pd.Series, a: str | None, b: str | None) -> dict:
|
||||||
|
x = _panel()
|
||||||
|
idx = x.index
|
||||||
|
msk = idx >= (a or idx[0])
|
||||||
|
if b is not None:
|
||||||
|
msk &= idx <= b
|
||||||
|
x = x[msk]
|
||||||
|
y = y.reindex(x.index)
|
||||||
|
ok = y.notna() & x.notna().all(axis=1)
|
||||||
|
if ok.sum() < 252:
|
||||||
|
return {}
|
||||||
|
X = np.column_stack([np.ones(int(ok.sum()))] +
|
||||||
|
[x[s][ok].to_numpy() for s in SYMS])
|
||||||
|
yn = y[ok].to_numpy()
|
||||||
|
beta, *_ = np.linalg.lstsq(X, yn, rcond=None)
|
||||||
|
res = yn - X @ beta
|
||||||
|
dof = max(int(ok.sum()) - len(SYMS) - 1, 1)
|
||||||
|
sigma2 = float(res @ res) / dof
|
||||||
|
se = np.sqrt(np.diag(np.linalg.inv(X.T @ X)) * sigma2)
|
||||||
|
t = np.where(se > 0, beta / se, 0.0)
|
||||||
|
r2 = 1 - float(res @ res) / float((yn - yn.mean()) @ (yn - yn.mean()))
|
||||||
|
return {
|
||||||
|
"n": int(ok.sum()),
|
||||||
|
"start": str(x.index[ok][0].date()),
|
||||||
|
"end": str(x.index[ok][-1].date()),
|
||||||
|
"r2": float(r2),
|
||||||
|
"alpha_ann": float(beta[0] * 252),
|
||||||
|
"alpha_t": float(t[0]),
|
||||||
|
"factors": [
|
||||||
|
{"name": INV[s], "sym": s, "beta": float(beta[k + 1]),
|
||||||
|
"t": float(t[k + 1])}
|
||||||
|
for k, s in enumerate(SYMS)],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _forward(y: pd.Series, a: str | None, b: str | None) -> list[str]:
|
||||||
|
"""BIC-gated forward selection over the battery -> identified sleeves."""
|
||||||
|
x = _panel()
|
||||||
|
idx = x.index
|
||||||
|
msk = idx >= (a or idx[0])
|
||||||
|
if b is not None:
|
||||||
|
msk &= idx <= b
|
||||||
|
x = x[msk]
|
||||||
|
y = y.reindex(x.index)
|
||||||
|
ok = y.notna()
|
||||||
|
if ok.sum() < 252:
|
||||||
|
return []
|
||||||
|
cand = {s: x[s].to_numpy() for s in SYMS}
|
||||||
|
chosen, _m, _okk = decompose.forward_select(y.to_numpy(), cand, y_ok=ok)
|
||||||
|
return list(chosen)
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------- commentary
|
||||||
|
# human meaning of each sleeve (used for the prose)
|
||||||
|
MEANING: dict[str, str] = {
|
||||||
|
"efa": "international developed markets", "vwo": "emerging markets",
|
||||||
|
"vug": "US growth equities", "vtv": "US value equities",
|
||||||
|
"iwm": "US small caps", "rsp": "equal-weight (small-tilted) US",
|
||||||
|
"usmv": "low volatility", "dflvx": "low volatility",
|
||||||
|
"qual": "quality (high-ROE, low-debt, stable earnings)",
|
||||||
|
"mtum": "momentum (recent winners)", "hdv": "high dividend",
|
||||||
|
"vym": "high dividend (appreciation-tilted)",
|
||||||
|
"tlt": "long-duration Treasuries", "gld": "gold",
|
||||||
|
"fxe": "the euro", "fxy": "the yen", "fxu": "the Australian dollar",
|
||||||
|
"xlu": "utilities (defensive bond-proxy)",
|
||||||
|
"xlp": "consumer staples (defensive)",
|
||||||
|
"xlv": "healthcare (defensive)", "xlf": "banks/financials",
|
||||||
|
"xle": "energy",
|
||||||
|
}
|
||||||
|
# sign-specific phrasing where the generic 'tilt toward/away from' is wrong
|
||||||
|
SPECIAL: dict[tuple[str, bool], str] = {
|
||||||
|
("fxe", False): ("short-euro position that carries the USD/EUR "
|
||||||
|
"interest-rate differential"),
|
||||||
|
("fxy", False): ("short-yen position that carries the USD/JPY "
|
||||||
|
"rate differential"),
|
||||||
|
("fxu", False): "short-AUD position (USD carry)",
|
||||||
|
("fxu", True): "long-AUD position (AUD carry)",
|
||||||
|
("fxe", True): "long-euro position (exposed to EUR moves)",
|
||||||
|
("fxy", True): "long-yen position (safe-haven/carry)",
|
||||||
|
("qual", False): ("anti-quality tilt - systematically underweight "
|
||||||
|
"high-ROE, low-debt names; the mechanical flip side "
|
||||||
|
"of a high-payout dividend mandate"),
|
||||||
|
("qual", True): "quality tilt (high-ROE, low-debt, stable earnings)",
|
||||||
|
("mtum", False): ("anti-momentum character - it does not chase "
|
||||||
|
"recent winners (low-turnover/contrarian)"),
|
||||||
|
("mtum", True): "momentum tilt (preference for recent winners)",
|
||||||
|
("hdv", True): ("high-dividend tilt - a systematic preference for "
|
||||||
|
"income-paying names"),
|
||||||
|
("hdv", False): "underweight to high-dividend names",
|
||||||
|
("vym", True): "dividend-appreciation tilt (growing payers)",
|
||||||
|
("rsp", False): "cap-weight concentration (tilt away from "
|
||||||
|
"equal-weight/small)",
|
||||||
|
("rsp", True): "equal-weight (small-tilted) exposure",
|
||||||
|
("vwo", False): "developed-only tilt (away from emerging markets)",
|
||||||
|
("vwo", True): "an emerging-market tilt",
|
||||||
|
("usmv", True): "low-volatility (defensive beta) tilt",
|
||||||
|
("dflvx", True): "low-volatility (defensive beta) tilt",
|
||||||
|
("dflvx", False): "underweight to low-volatility names",
|
||||||
|
("usmv", False): "underweight to low-volatility names",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _strength(t: float) -> str:
|
||||||
|
a = abs(t)
|
||||||
|
return "strong" if a >= 10 else "clear" if a >= 5 else "modest"
|
||||||
|
|
||||||
|
|
||||||
|
def _tilt_sentence(f: dict) -> str:
|
||||||
|
s = f["sym"]
|
||||||
|
key = (s, f["beta"] > 0)
|
||||||
|
if key in SPECIAL:
|
||||||
|
body = SPECIAL[key]
|
||||||
|
else:
|
||||||
|
m = MEANING.get(s, f["name"])
|
||||||
|
body = (f"tilt toward {m}" if f["beta"] > 0
|
||||||
|
else f"tilt away from {m}")
|
||||||
|
return (f"{_strength(f['t'])} {body} "
|
||||||
|
f"(β {f['beta']:+.2f}, t {f['t']:+.0f})")
|
||||||
|
|
||||||
|
|
||||||
|
def commentary(sym: str, prof: dict) -> list[str]:
|
||||||
|
"""English prose for the style-tilt block (data-driven)."""
|
||||||
|
if not prof or not prof.get("full"):
|
||||||
|
return []
|
||||||
|
full, rec5 = prof["full"], prof.get("rec5") or {}
|
||||||
|
sig_full = {f["sym"]: f for f in full["factors"] if abs(f["t"]) >= 2}
|
||||||
|
sig_5 = {f["sym"]: f for f in rec5.get("factors", [])
|
||||||
|
if abs(f["t"]) >= 2}
|
||||||
|
out = []
|
||||||
|
# paragraph 1: the identified stack
|
||||||
|
parts = []
|
||||||
|
core = sig_full.get("efa")
|
||||||
|
if core:
|
||||||
|
parts.append(
|
||||||
|
f"the core exposure is {abs(core['beta']):.0%} of "
|
||||||
|
f"international developed equities (t {core['t']:+.0f})")
|
||||||
|
for f in sorted(sig_full.values(), key=lambda x: -abs(x["t"])):
|
||||||
|
if f["sym"] == "efa":
|
||||||
|
continue
|
||||||
|
parts.append(_tilt_sentence(f))
|
||||||
|
if parts:
|
||||||
|
out.append(
|
||||||
|
f"Style-tilt analysis (22 style/asset sleeves regressed on "
|
||||||
|
f"the fund's excess returns; US funds proxying the global "
|
||||||
|
f"factors): over {full['start'][:4]}-to-{full['end'][:4]} the "
|
||||||
|
f"fit explains {full['r2']:.0%} of the excess return (R² "
|
||||||
|
f"{full['r2']:.2f}). The statistically identified tilt stack: "
|
||||||
|
+ "; ".join(parts) + ".")
|
||||||
|
# factors that only appear in the 5y window
|
||||||
|
recent_only = [s for s in sig_5
|
||||||
|
if s not in sig_full and s != "efa"]
|
||||||
|
if recent_only:
|
||||||
|
out.append(
|
||||||
|
"Visible only in the recent 5-year window: "
|
||||||
|
+ "; ".join(_tilt_sentence(sig_5[s]) for s in recent_only)
|
||||||
|
+ " - newer behavior, or a factor the longer sample dilutes.")
|
||||||
|
# paragraph 2: the residual - is there skill left?
|
||||||
|
a, t = full["alpha_ann"], full["alpha_t"]
|
||||||
|
if abs(t) < 1.75:
|
||||||
|
out.append(
|
||||||
|
f"After stripping the identified tilts, the residual excess "
|
||||||
|
f"return is {a * 100:+.1f}%/year (t {t:+.1f}) - NOT "
|
||||||
|
f"statistically significant: the fund's outperformance is "
|
||||||
|
f"factor exposure, not skill alpha.")
|
||||||
|
else:
|
||||||
|
out.append(
|
||||||
|
f"After stripping the identified tilts, a significant "
|
||||||
|
f"residual of {a * 100:+.1f}%/year (t {t:+.1f}) remains - "
|
||||||
|
f"genuine alpha on top of the factor stack.")
|
||||||
|
out.append(
|
||||||
|
"Caveat: the sleeves are US funds proxying global factors; the "
|
||||||
|
"fund expresses them in its own holdings, so the betas are the "
|
||||||
|
"right sign and magnitude but approximate. An index-matched "
|
||||||
|
"benchmark (the fund's own published index, when one exists) "
|
||||||
|
"would absorb part of the residual as well.")
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def style_profile(sym: str) -> dict | None:
|
||||||
|
"""Full + 5y battery fits, the BIC-identified stack, and commentary.
|
||||||
|
|
||||||
|
Returns None when the fund has no usable local history."""
|
||||||
|
y = _fund_excess(sym)
|
||||||
|
if len(y.dropna()) < 252:
|
||||||
|
return None
|
||||||
|
full = _fit(y, None, None)
|
||||||
|
if not full:
|
||||||
|
return None
|
||||||
|
rec5 = _fit(y, "2021-01-01", None)
|
||||||
|
prof = {"full": full,
|
||||||
|
"rec5": rec5 or {},
|
||||||
|
"identified": _forward(y, None, None)}
|
||||||
|
prof["commentary"] = commentary(sym, prof)
|
||||||
|
return prof
|
||||||
0
overrides/corrections/.gitkeep
Normal file
0
overrides/corrections/.gitkeep
Normal file
2
overrides/frozen/aaalx-capitalGain.csv
Normal file
2
overrides/frozen/aaalx-capitalGain.csv
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
Date,Capital Gains
|
||||||
|
2022-12-28,0.007000
|
||||||
|
6
overrides/frozen/aaalx-dividend.csv
Normal file
6
overrides/frozen/aaalx-dividend.csv
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
Date,Dividends
|
||||||
|
2024-12-20,0.399900
|
||||||
|
2025-04-08,0.065200
|
||||||
|
2021-12-28,0.250300
|
||||||
|
2022-12-28,0.007100
|
||||||
|
2023-12-21,0.280200
|
||||||
|
1034
overrides/frozen/aaalx-history.csv
Normal file
1034
overrides/frozen/aaalx-history.csv
Normal file
File diff suppressed because it is too large
Load Diff
7
overrides/frozen/aaalx.json
Normal file
7
overrides/frozen/aaalx.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"symbol": "aaalx",
|
||||||
|
"longName": "American Century Asset Allocation Portfolios Inc. - One Choice Blend 2015\u00a0Portfolio Fund",
|
||||||
|
"freeze_date": "2025-04-17",
|
||||||
|
"created": "2026-08-31",
|
||||||
|
"reason": "yahoo-empty"
|
||||||
|
}
|
||||||
4
overrides/frozen/abqzx-capitalGain.csv
Normal file
4
overrides/frozen/abqzx-capitalGain.csv
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
Date,Capital Gains
|
||||||
|
2021-12-03,0.018000
|
||||||
|
2016-12-07,0.040000
|
||||||
|
2020-12-04,0.145000
|
||||||
|
76
overrides/frozen/abqzx-dividend.csv
Normal file
76
overrides/frozen/abqzx-dividend.csv
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
Date,Dividends
|
||||||
|
2019-02-28,0.027378
|
||||||
|
2019-06-28,0.032440
|
||||||
|
2020-09-30,0.029451
|
||||||
|
2021-09-30,0.021411
|
||||||
|
2023-09-29,0.030585
|
||||||
|
2024-03-28,0.033582
|
||||||
|
2024-07-31,0.036753
|
||||||
|
2019-10-31,0.028129
|
||||||
|
2021-11-30,0.015153
|
||||||
|
2019-07-31,0.029595
|
||||||
|
2019-11-29,0.032274
|
||||||
|
2024-11-29,0.033543
|
||||||
|
2020-01-31,0.033029
|
||||||
|
2020-04-30,0.027369
|
||||||
|
2022-04-29,0.022921
|
||||||
|
2024-10-31,0.033149
|
||||||
|
2019-01-31,0.029606
|
||||||
|
2021-02-26,0.027489
|
||||||
|
2021-03-31,0.030588
|
||||||
|
2021-07-30,0.025064
|
||||||
|
2023-11-30,0.031725
|
||||||
|
2021-05-28,0.024247
|
||||||
|
2021-08-31,0.021447
|
||||||
|
2021-12-03,0.017700
|
||||||
|
2024-04-30,0.033871
|
||||||
|
2020-03-31,0.027427
|
||||||
|
2021-01-29,0.027906
|
||||||
|
2022-12-30,0.033246
|
||||||
|
2023-04-28,0.029077
|
||||||
|
2024-08-30,0.042260
|
||||||
|
2020-12-04,0.144700
|
||||||
|
2022-12-02,0.044800
|
||||||
|
2023-06-30,0.032841
|
||||||
|
2024-06-28,0.031146
|
||||||
|
2023-01-31,0.036682
|
||||||
|
2019-03-29,0.033541
|
||||||
|
2019-08-30,0.032235
|
||||||
|
2020-02-28,0.028150
|
||||||
|
2020-06-30,0.028395
|
||||||
|
2020-08-31,0.027902
|
||||||
|
2021-10-29,0.020966
|
||||||
|
2022-11-30,0.032311
|
||||||
|
2024-12-31,0.030620
|
||||||
|
2022-02-28,0.022998
|
||||||
|
2022-08-31,0.030780
|
||||||
|
2020-10-30,0.031190
|
||||||
|
2020-11-30,0.026206
|
||||||
|
2020-12-31,0.027202
|
||||||
|
2022-03-31,0.021258
|
||||||
|
2022-09-30,0.023069
|
||||||
|
2023-03-31,0.037445
|
||||||
|
2023-05-31,0.034867
|
||||||
|
2024-01-31,0.033743
|
||||||
|
2019-04-30,0.033428
|
||||||
|
2020-05-29,0.031073
|
||||||
|
2021-04-30,0.028135
|
||||||
|
2022-01-31,0.018929
|
||||||
|
2023-10-31,0.028526
|
||||||
|
2024-05-31,0.036527
|
||||||
|
2019-05-31,0.036744
|
||||||
|
2019-09-30,0.028360
|
||||||
|
2019-12-31,0.031747
|
||||||
|
2022-06-30,0.021610
|
||||||
|
2022-10-31,0.027292
|
||||||
|
2023-12-29,0.033158
|
||||||
|
2024-02-29,0.037804
|
||||||
|
2021-06-30,0.021983
|
||||||
|
2021-12-31,0.024863
|
||||||
|
2022-05-31,0.026023
|
||||||
|
2022-07-29,0.032376
|
||||||
|
2023-02-28,0.033407
|
||||||
|
2024-09-30,0.030860
|
||||||
|
2020-07-31,0.032462
|
||||||
|
2023-07-31,0.030966
|
||||||
|
2023-08-31,0.036161
|
||||||
|
1516
overrides/frozen/abqzx-history.csv
Normal file
1516
overrides/frozen/abqzx-history.csv
Normal file
File diff suppressed because it is too large
Load Diff
7
overrides/frozen/abqzx.json
Normal file
7
overrides/frozen/abqzx.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"symbol": "abqzx",
|
||||||
|
"longName": "AB Bond Fund, Inc. - AB Total Return Bond Portfolio",
|
||||||
|
"freeze_date": "2025-01-08",
|
||||||
|
"created": "2026-08-31",
|
||||||
|
"reason": "yahoo-empty"
|
||||||
|
}
|
||||||
1
overrides/frozen/adusx-dividend.csv
Normal file
1
overrides/frozen/adusx-dividend.csv
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Date,Dividends,ctime
|
||||||
|
503
overrides/frozen/adusx-history.csv
Normal file
503
overrides/frozen/adusx-history.csv
Normal file
|
|
@ -0,0 +1,503 @@
|
||||||
|
Date,Open,High,Low,Close,Adj Close,Volume,ctime
|
||||||
|
2015-12-21,15.000000,15.000000,15.000000,15.000000,15.000000,0,2017-08-22
|
||||||
|
2015-12-22,14.960000,14.960000,14.960000,14.960000,14.960000,0,2017-08-22
|
||||||
|
2015-12-23,14.970000,14.970000,14.970000,14.970000,14.970000,0,2017-08-22
|
||||||
|
2015-12-24,14.990000,14.990000,14.990000,14.990000,14.990000,0,2017-08-22
|
||||||
|
2015-12-28,14.990000,14.990000,14.990000,14.990000,14.990000,0,2017-08-22
|
||||||
|
2015-12-29,15.010000,15.010000,15.010000,15.010000,15.010000,0,2017-08-22
|
||||||
|
2015-12-30,15.000000,15.000000,15.000000,15.000000,15.000000,0,2017-08-22
|
||||||
|
2015-12-31,15.010000,15.010000,15.010000,15.010000,15.010000,0,2017-08-22
|
||||||
|
2016-01-04,14.980000,14.980000,14.980000,14.980000,14.980000,0,2017-08-22
|
||||||
|
2016-01-05,15.010000,15.010000,15.010000,15.010000,15.010000,0,2017-08-22
|
||||||
|
2016-01-06,15.050000,15.050000,15.050000,15.050000,15.050000,0,2017-08-22
|
||||||
|
2016-01-07,15.010000,15.010000,15.010000,15.010000,15.010000,0,2017-08-22
|
||||||
|
2016-01-08,15.020000,15.020000,15.020000,15.020000,15.020000,0,2017-08-22
|
||||||
|
2016-01-11,15.090000,15.090000,15.090000,15.090000,15.090000,0,2017-08-22
|
||||||
|
2016-01-12,15.150000,15.150000,15.150000,15.150000,15.150000,0,2017-08-22
|
||||||
|
2016-01-13,15.090000,15.090000,15.090000,15.090000,15.090000,0,2017-08-22
|
||||||
|
2016-01-14,15.080000,15.080000,15.080000,15.080000,15.080000,0,2017-08-22
|
||||||
|
2016-01-15,15.010000,15.010000,15.010000,15.010000,15.010000,0,2017-08-22
|
||||||
|
2016-01-19,15.120000,15.120000,15.120000,15.120000,15.120000,0,2017-08-22
|
||||||
|
2016-01-20,15.090000,15.090000,15.090000,15.090000,15.090000,0,2017-08-22
|
||||||
|
2016-01-21,15.050000,15.050000,15.050000,15.050000,15.050000,0,2017-08-22
|
||||||
|
2016-01-22,15.100000,15.100000,15.100000,15.100000,15.100000,0,2017-08-22
|
||||||
|
2016-01-25,15.090000,15.090000,15.090000,15.090000,15.090000,0,2017-08-22
|
||||||
|
2016-01-26,15.100000,15.100000,15.100000,15.100000,15.100000,0,2017-08-22
|
||||||
|
2016-01-27,15.090000,15.090000,15.090000,15.090000,15.090000,0,2017-08-22
|
||||||
|
2016-01-28,15.140000,15.140000,15.140000,15.140000,15.140000,0,2017-08-22
|
||||||
|
2016-01-29,15.170000,15.170000,15.170000,15.170000,15.170000,0,2017-08-22
|
||||||
|
2016-02-01,15.190000,15.190000,15.190000,15.190000,15.190000,0,2017-08-22
|
||||||
|
2016-02-02,15.220000,15.220000,15.220000,15.220000,15.220000,0,2017-08-22
|
||||||
|
2016-02-03,15.140000,15.140000,15.140000,15.140000,15.140000,0,2017-08-22
|
||||||
|
2016-02-04,15.020000,15.020000,15.020000,15.020000,15.020000,0,2017-08-22
|
||||||
|
2016-02-05,15.000000,15.000000,15.000000,15.000000,15.000000,0,2017-08-22
|
||||||
|
2016-02-08,15.010000,15.010000,15.010000,15.010000,15.010000,0,2017-08-22
|
||||||
|
2016-02-09,15.050000,15.050000,15.050000,15.050000,15.050000,0,2017-08-22
|
||||||
|
2016-02-10,15.070000,15.070000,15.070000,15.070000,15.070000,0,2017-08-22
|
||||||
|
2016-02-11,15.090000,15.090000,15.090000,15.090000,15.090000,0,2017-08-22
|
||||||
|
2016-02-12,15.060000,15.060000,15.060000,15.060000,15.060000,0,2017-08-22
|
||||||
|
2016-02-16,15.010000,15.010000,15.010000,15.010000,15.010000,0,2017-08-22
|
||||||
|
2016-02-17,14.960000,14.960000,14.960000,14.960000,14.960000,0,2017-08-22
|
||||||
|
2016-02-18,14.920000,14.920000,14.920000,14.920000,14.920000,0,2017-08-22
|
||||||
|
2016-02-19,14.940000,14.940000,14.940000,14.940000,14.940000,0,2017-08-22
|
||||||
|
2016-02-22,14.860000,14.860000,14.860000,14.860000,14.860000,0,2017-08-22
|
||||||
|
2016-02-23,14.890000,14.890000,14.890000,14.890000,14.890000,0,2017-08-22
|
||||||
|
2016-02-24,14.890000,14.890000,14.890000,14.890000,14.890000,0,2017-08-22
|
||||||
|
2016-02-25,14.910000,14.910000,14.910000,14.910000,14.910000,0,2017-08-22
|
||||||
|
2016-02-26,14.840000,14.840000,14.840000,14.840000,14.840000,0,2017-08-22
|
||||||
|
2016-02-29,14.790000,14.790000,14.790000,14.790000,14.790000,0,2017-08-22
|
||||||
|
2016-03-01,14.710000,14.710000,14.710000,14.710000,14.710000,0,2017-08-22
|
||||||
|
2016-03-02,14.710000,14.710000,14.710000,14.710000,14.710000,0,2017-08-22
|
||||||
|
2016-03-03,14.640000,14.640000,14.640000,14.640000,14.640000,0,2017-08-22
|
||||||
|
2016-03-04,14.600000,14.600000,14.600000,14.600000,14.600000,0,2017-08-22
|
||||||
|
2016-03-07,14.520000,14.520000,14.520000,14.520000,14.520000,0,2017-08-22
|
||||||
|
2016-03-08,14.610000,14.610000,14.610000,14.610000,14.610000,0,2017-08-22
|
||||||
|
2016-03-09,14.640000,14.640000,14.640000,14.640000,14.640000,0,2017-08-22
|
||||||
|
2016-03-10,14.700000,14.700000,14.700000,14.700000,14.700000,0,2017-08-22
|
||||||
|
2016-03-11,14.710000,14.710000,14.710000,14.710000,14.710000,0,2017-08-22
|
||||||
|
2016-03-14,14.740000,14.740000,14.740000,14.740000,14.740000,0,2017-08-22
|
||||||
|
2016-03-15,14.790000,14.790000,14.790000,14.790000,14.790000,0,2017-08-22
|
||||||
|
2016-03-16,14.780000,14.780000,14.780000,14.780000,14.780000,0,2017-08-22
|
||||||
|
2016-03-17,14.720000,14.720000,14.720000,14.720000,14.720000,0,2017-08-22
|
||||||
|
2016-03-18,14.710000,14.710000,14.710000,14.710000,14.710000,0,2017-08-22
|
||||||
|
2016-03-21,14.740000,14.740000,14.740000,14.740000,14.740000,0,2017-08-22
|
||||||
|
2016-03-22,14.720000,14.720000,14.720000,14.720000,14.720000,0,2017-08-22
|
||||||
|
2016-03-23,14.800000,14.800000,14.800000,14.800000,14.800000,0,2017-08-22
|
||||||
|
2016-03-24,14.790000,14.790000,14.790000,14.790000,14.790000,0,2017-08-22
|
||||||
|
2016-03-28,14.790000,14.790000,14.790000,14.790000,14.790000,0,2017-08-22
|
||||||
|
2016-03-29,14.800000,14.800000,14.800000,14.800000,14.800000,0,2017-08-22
|
||||||
|
2016-03-30,14.810000,14.810000,14.810000,14.810000,14.810000,0,2017-08-22
|
||||||
|
2016-03-31,14.790000,14.790000,14.790000,14.790000,14.790000,0,2017-08-22
|
||||||
|
2016-04-01,14.820000,14.820000,14.820000,14.820000,14.820000,0,2017-08-22
|
||||||
|
2016-04-04,14.880000,14.880000,14.880000,14.880000,14.880000,0,2017-08-22
|
||||||
|
2016-04-05,14.950000,14.950000,14.950000,14.950000,14.950000,0,2017-08-22
|
||||||
|
2016-04-06,14.980000,14.980000,14.980000,14.980000,14.980000,0,2017-08-22
|
||||||
|
2016-04-07,15.010000,15.010000,15.010000,15.010000,15.010000,0,2017-08-22
|
||||||
|
2016-04-08,15.020000,15.020000,15.020000,15.020000,15.020000,0,2017-08-22
|
||||||
|
2016-04-11,14.990000,14.990000,14.990000,14.990000,14.990000,0,2017-08-22
|
||||||
|
2016-04-12,15.000000,15.000000,15.000000,15.000000,15.000000,0,2017-08-22
|
||||||
|
2016-04-13,14.880000,14.880000,14.880000,14.880000,14.880000,0,2017-08-22
|
||||||
|
2016-04-14,14.880000,14.880000,14.880000,14.880000,14.880000,0,2017-08-22
|
||||||
|
2016-04-15,14.870000,14.870000,14.870000,14.870000,14.870000,0,2017-08-22
|
||||||
|
2016-04-18,14.870000,14.870000,14.870000,14.870000,14.870000,0,2017-08-22
|
||||||
|
2016-04-19,14.890000,14.890000,14.890000,14.890000,14.890000,0,2017-08-22
|
||||||
|
2016-04-20,14.870000,14.870000,14.870000,14.870000,14.870000,0,2017-08-22
|
||||||
|
2016-04-21,14.820000,14.820000,14.820000,14.820000,14.820000,0,2017-08-22
|
||||||
|
2016-04-22,14.720000,14.720000,14.720000,14.720000,14.720000,0,2017-08-22
|
||||||
|
2016-04-25,14.800000,14.800000,14.800000,14.800000,14.800000,0,2017-08-22
|
||||||
|
2016-04-26,14.780000,14.780000,14.780000,14.780000,14.780000,0,2017-08-22
|
||||||
|
2016-04-27,14.760000,14.760000,14.760000,14.760000,14.760000,0,2017-08-22
|
||||||
|
2016-04-28,14.800000,14.800000,14.800000,14.800000,14.800000,0,2017-08-22
|
||||||
|
2016-04-29,14.790000,14.790000,14.790000,14.790000,14.790000,0,2017-08-22
|
||||||
|
2016-05-02,14.850000,14.850000,14.850000,14.850000,14.850000,0,2017-08-22
|
||||||
|
2016-05-03,14.870000,14.870000,14.870000,14.870000,14.870000,0,2017-08-22
|
||||||
|
2016-05-04,15.010000,15.010000,15.010000,15.010000,15.010000,0,2017-08-22
|
||||||
|
2016-05-05,15.050000,15.050000,15.050000,15.050000,15.050000,0,2017-08-22
|
||||||
|
2016-05-06,15.060000,15.060000,15.060000,15.060000,15.060000,0,2017-08-22
|
||||||
|
2016-05-09,15.150000,15.150000,15.150000,15.150000,15.150000,0,2017-08-22
|
||||||
|
2016-05-10,15.170000,15.170000,15.170000,15.170000,15.170000,0,2017-08-22
|
||||||
|
2016-05-11,15.160000,15.160000,15.160000,15.160000,15.160000,0,2017-08-22
|
||||||
|
2016-05-12,15.180000,15.180000,15.180000,15.180000,15.180000,0,2017-08-22
|
||||||
|
2016-05-13,15.210000,15.210000,15.210000,15.210000,15.210000,0,2017-08-22
|
||||||
|
2016-05-16,15.190000,15.190000,15.190000,15.190000,15.190000,0,2017-08-22
|
||||||
|
2016-05-17,15.100000,15.100000,15.100000,15.100000,15.100000,0,2017-08-22
|
||||||
|
2016-05-18,15.170000,15.170000,15.170000,15.170000,15.170000,0,2017-08-22
|
||||||
|
2016-05-20,15.140000,15.140000,15.140000,15.140000,15.140000,0,2017-08-22
|
||||||
|
2016-05-23,15.080000,15.080000,15.080000,15.080000,15.080000,0,2017-08-22
|
||||||
|
2016-05-24,15.100000,15.100000,15.100000,15.100000,15.100000,0,2017-08-22
|
||||||
|
2016-05-25,15.040000,15.040000,15.040000,15.040000,15.040000,0,2017-08-22
|
||||||
|
2016-05-26,15.080000,15.080000,15.080000,15.080000,15.080000,0,2017-08-22
|
||||||
|
2016-05-27,15.070000,15.070000,15.070000,15.070000,15.070000,0,2017-08-22
|
||||||
|
2016-05-31,15.040000,15.040000,15.040000,15.040000,15.040000,0,2017-08-22
|
||||||
|
2016-06-01,15.060000,15.060000,15.060000,15.060000,15.060000,0,2017-08-22
|
||||||
|
2016-06-02,15.030000,15.030000,15.030000,15.030000,15.030000,0,2017-08-22
|
||||||
|
2016-06-03,15.030000,15.030000,15.030000,15.030000,15.030000,0,2017-08-22
|
||||||
|
2016-06-06,14.930000,14.930000,14.930000,14.930000,14.930000,0,2017-08-22
|
||||||
|
2016-06-07,14.910000,14.910000,14.910000,14.910000,14.910000,0,2017-08-22
|
||||||
|
2016-06-08,14.950000,14.950000,14.950000,14.950000,14.950000,0,2017-08-22
|
||||||
|
2016-06-09,14.990000,14.990000,14.990000,14.990000,14.990000,0,2017-08-22
|
||||||
|
2016-06-10,15.040000,15.040000,15.040000,15.040000,15.040000,0,2017-08-22
|
||||||
|
2016-06-13,15.070000,15.070000,15.070000,15.070000,15.070000,0,2017-08-22
|
||||||
|
2016-06-14,15.090000,15.090000,15.090000,15.090000,15.090000,0,2017-08-22
|
||||||
|
2016-06-15,15.050000,15.050000,15.050000,15.050000,15.050000,0,2017-08-22
|
||||||
|
2016-06-16,15.060000,15.060000,15.060000,15.060000,15.060000,0,2017-08-22
|
||||||
|
2016-06-17,15.000000,15.000000,15.000000,15.000000,15.000000,0,2017-08-22
|
||||||
|
2016-06-20,14.920000,14.920000,14.920000,14.920000,14.920000,0,2017-08-22
|
||||||
|
2016-06-21,14.990000,14.990000,14.990000,14.990000,14.990000,0,2017-08-22
|
||||||
|
2016-06-22,14.980000,14.980000,14.980000,14.980000,14.980000,0,2017-08-22
|
||||||
|
2016-06-23,14.910000,14.910000,14.910000,14.910000,14.910000,0,2017-08-22
|
||||||
|
2016-06-24,15.090000,15.090000,15.090000,15.090000,15.090000,0,2017-08-22
|
||||||
|
2016-06-27,15.250000,15.250000,15.250000,15.250000,15.250000,0,2017-08-22
|
||||||
|
2016-06-28,15.190000,15.190000,15.190000,15.190000,15.190000,0,2017-08-22
|
||||||
|
2016-06-29,15.140000,15.140000,15.140000,15.140000,15.140000,0,2017-08-22
|
||||||
|
2016-06-30,15.150000,15.150000,15.150000,15.150000,15.150000,0,2017-08-22
|
||||||
|
2016-07-01,15.070000,15.070000,15.070000,15.070000,15.070000,0,2017-08-22
|
||||||
|
2016-07-05,15.210000,15.210000,15.210000,15.210000,15.210000,0,2017-08-22
|
||||||
|
2016-07-06,15.180000,15.180000,15.180000,15.180000,15.180000,0,2017-08-22
|
||||||
|
2016-07-07,15.210000,15.210000,15.210000,15.210000,15.210000,0,2017-08-22
|
||||||
|
2016-07-08,15.170000,15.170000,15.170000,15.170000,15.170000,0,2017-08-22
|
||||||
|
2016-07-11,15.120000,15.120000,15.120000,15.120000,15.120000,0,2017-08-22
|
||||||
|
2016-07-12,14.970000,14.970000,14.970000,14.970000,14.970000,0,2017-08-22
|
||||||
|
2016-07-13,14.970000,14.970000,14.970000,14.970000,14.970000,0,2017-08-22
|
||||||
|
2016-07-14,14.990000,14.990000,14.990000,14.990000,14.990000,0,2017-08-22
|
||||||
|
2016-07-15,15.000000,15.000000,15.000000,15.000000,15.000000,0,2017-08-22
|
||||||
|
2016-07-18,14.990000,14.990000,14.990000,14.990000,14.990000,0,2017-08-22
|
||||||
|
2016-07-19,15.110000,15.110000,15.110000,15.110000,15.110000,0,2017-08-22
|
||||||
|
2016-07-20,15.070000,15.070000,15.070000,15.070000,15.070000,0,2017-08-22
|
||||||
|
2016-07-21,14.980000,14.980000,14.980000,14.980000,14.980000,0,2017-08-22
|
||||||
|
2016-07-22,15.020000,15.020000,15.020000,15.020000,15.020000,0,2017-08-22
|
||||||
|
2016-07-25,15.010000,15.010000,15.010000,15.010000,15.010000,0,2017-08-22
|
||||||
|
2016-07-26,14.870000,14.870000,14.870000,14.870000,14.870000,0,2017-08-22
|
||||||
|
2016-07-27,14.890000,14.890000,14.890000,14.890000,14.890000,0,2017-08-22
|
||||||
|
2016-07-28,14.960000,14.960000,14.960000,14.960000,14.960000,0,2017-08-22
|
||||||
|
2016-07-29,14.960000,14.960000,14.960000,14.960000,14.960000,0,2017-08-22
|
||||||
|
2016-08-01,14.990000,14.990000,14.990000,14.990000,14.990000,0,2017-08-22
|
||||||
|
2016-08-02,15.070000,15.070000,15.070000,15.070000,15.070000,0,2017-08-22
|
||||||
|
2016-08-03,15.060000,15.060000,15.060000,15.060000,15.060000,0,2017-08-22
|
||||||
|
2016-08-04,15.010000,15.010000,15.010000,15.010000,15.010000,0,2017-08-22
|
||||||
|
2016-08-05,14.950000,14.950000,14.950000,14.950000,14.950000,0,2017-08-22
|
||||||
|
2016-08-08,14.920000,14.920000,14.920000,14.920000,14.920000,0,2017-08-22
|
||||||
|
2016-08-09,14.940000,14.940000,14.940000,14.940000,14.940000,0,2017-08-22
|
||||||
|
2016-08-10,14.930000,14.930000,14.930000,14.930000,14.930000,0,2017-08-22
|
||||||
|
2016-08-11,14.900000,14.900000,14.900000,14.900000,14.900000,0,2017-08-22
|
||||||
|
2016-08-12,14.910000,14.910000,14.910000,14.910000,14.910000,0,2017-08-22
|
||||||
|
2016-08-15,14.880000,14.880000,14.880000,14.880000,14.880000,0,2017-08-22
|
||||||
|
2016-08-16,14.780000,14.780000,14.780000,14.780000,14.780000,0,2017-08-22
|
||||||
|
2016-08-17,14.850000,14.850000,14.850000,14.850000,14.850000,0,2017-08-22
|
||||||
|
2016-08-18,14.840000,14.840000,14.840000,14.840000,14.840000,0,2017-08-22
|
||||||
|
2016-08-19,14.840000,14.840000,14.840000,14.840000,14.840000,0,2017-08-22
|
||||||
|
2016-08-22,14.870000,14.870000,14.870000,14.870000,14.870000,0,2017-08-22
|
||||||
|
2016-08-23,14.870000,14.870000,14.870000,14.870000,14.870000,0,2017-08-22
|
||||||
|
2016-08-24,14.850000,14.850000,14.850000,14.850000,14.850000,0,2017-08-22
|
||||||
|
2016-08-25,14.780000,14.780000,14.780000,14.780000,14.780000,0,2017-08-22
|
||||||
|
2016-08-26,14.820000,14.820000,14.820000,14.820000,14.820000,0,2017-08-22
|
||||||
|
2016-08-29,14.810000,14.810000,14.810000,14.810000,14.810000,0,2017-08-22
|
||||||
|
2016-08-30,14.830000,14.830000,14.830000,14.830000,14.830000,0,2017-08-22
|
||||||
|
2016-08-31,14.840000,14.840000,14.840000,14.840000,14.840000,0,2017-08-22
|
||||||
|
2016-09-01,14.850000,14.850000,14.850000,14.850000,14.850000,0,2017-08-22
|
||||||
|
2016-09-02,14.830000,14.830000,14.830000,14.830000,14.830000,0,2017-08-22
|
||||||
|
2016-09-06,14.790000,14.790000,14.790000,14.790000,14.790000,0,2017-08-22
|
||||||
|
2016-09-07,14.770000,14.770000,14.770000,14.770000,14.770000,0,2017-08-22
|
||||||
|
2016-09-08,14.790000,14.790000,14.790000,14.790000,14.790000,0,2017-08-22
|
||||||
|
2016-09-09,14.910000,14.910000,14.910000,14.910000,14.910000,0,2017-08-22
|
||||||
|
2016-09-12,14.860000,14.860000,14.860000,14.860000,14.860000,0,2017-08-22
|
||||||
|
2016-09-13,14.910000,14.910000,14.910000,14.910000,14.910000,0,2017-08-22
|
||||||
|
2016-09-14,14.960000,14.960000,14.960000,14.960000,14.960000,0,2017-08-22
|
||||||
|
2016-09-15,14.930000,14.930000,14.930000,14.930000,14.930000,0,2017-08-22
|
||||||
|
2016-09-16,14.960000,14.960000,14.960000,14.960000,14.960000,0,2017-08-22
|
||||||
|
2016-09-19,14.950000,14.950000,14.950000,14.950000,14.950000,0,2017-08-22
|
||||||
|
2016-09-20,14.980000,14.980000,14.980000,14.980000,14.980000,0,2017-08-22
|
||||||
|
2016-09-21,14.950000,14.950000,14.950000,14.950000,14.950000,0,2017-08-22
|
||||||
|
2016-09-22,14.930000,14.930000,14.930000,14.930000,14.930000,0,2017-08-22
|
||||||
|
2016-09-23,14.910000,14.910000,14.910000,14.910000,14.910000,0,2017-08-22
|
||||||
|
2016-09-26,14.900000,14.900000,14.900000,14.900000,14.900000,0,2017-08-22
|
||||||
|
2016-09-27,14.880000,14.880000,14.880000,14.880000,14.880000,0,2017-08-22
|
||||||
|
2016-09-28,14.840000,14.840000,14.840000,14.840000,14.840000,0,2017-08-22
|
||||||
|
2016-09-29,14.790000,14.790000,14.790000,14.790000,14.790000,0,2017-08-22
|
||||||
|
2016-09-30,14.770000,14.770000,14.770000,14.770000,14.770000,0,2017-08-22
|
||||||
|
2016-10-03,14.770000,14.770000,14.770000,14.770000,14.770000,0,2017-08-22
|
||||||
|
2016-10-04,14.810000,14.810000,14.810000,14.810000,14.810000,0,2017-08-22
|
||||||
|
2016-10-05,14.810000,14.810000,14.810000,14.810000,14.810000,0,2017-08-22
|
||||||
|
2016-10-06,14.810000,14.810000,14.810000,14.810000,14.810000,0,2017-08-22
|
||||||
|
2016-10-07,14.850000,14.850000,14.850000,14.850000,14.850000,0,2017-08-22
|
||||||
|
2016-10-10,14.910000,14.910000,14.910000,14.910000,14.910000,0,2017-08-22
|
||||||
|
2016-10-11,14.890000,14.890000,14.890000,14.890000,14.890000,0,2017-08-22
|
||||||
|
2016-10-12,14.870000,14.870000,14.870000,14.870000,14.870000,0,2017-08-22
|
||||||
|
2016-10-13,14.860000,14.860000,14.860000,14.860000,14.860000,0,2017-08-22
|
||||||
|
2016-10-14,14.880000,14.880000,14.880000,14.880000,14.880000,0,2017-08-22
|
||||||
|
2016-10-17,14.860000,14.860000,14.860000,14.860000,14.860000,0,2017-08-22
|
||||||
|
2016-10-18,14.810000,14.810000,14.810000,14.810000,14.810000,0,2017-08-22
|
||||||
|
2016-10-19,14.730000,14.730000,14.730000,14.730000,14.730000,0,2017-08-22
|
||||||
|
2016-10-20,14.750000,14.750000,14.750000,14.750000,14.750000,0,2017-08-22
|
||||||
|
2016-10-21,14.780000,14.780000,14.780000,14.780000,14.780000,0,2017-08-22
|
||||||
|
2016-10-24,14.780000,14.780000,14.780000,14.780000,14.780000,0,2017-08-22
|
||||||
|
2016-10-25,14.800000,14.800000,14.800000,14.800000,14.800000,0,2017-08-22
|
||||||
|
2016-10-26,14.800000,14.800000,14.800000,14.800000,14.800000,0,2017-08-22
|
||||||
|
2016-10-27,14.750000,14.750000,14.750000,14.750000,14.750000,0,2017-08-22
|
||||||
|
2016-10-28,14.770000,14.770000,14.770000,14.770000,14.770000,0,2017-08-22
|
||||||
|
2016-10-31,14.710000,14.710000,14.710000,14.710000,14.710000,0,2017-08-22
|
||||||
|
2016-11-01,14.730000,14.730000,14.730000,14.730000,14.730000,0,2017-08-22
|
||||||
|
2016-11-02,14.620000,14.620000,14.620000,14.620000,14.620000,0,2017-08-22
|
||||||
|
2016-11-03,14.620000,14.620000,14.620000,14.620000,14.620000,0,2017-08-22
|
||||||
|
2016-11-04,14.600000,14.600000,14.600000,14.600000,14.600000,0,2017-08-22
|
||||||
|
2016-11-07,14.590000,14.590000,14.590000,14.590000,14.590000,0,2017-08-22
|
||||||
|
2016-11-08,14.600000,14.600000,14.600000,14.600000,14.600000,0,2017-08-22
|
||||||
|
2016-11-09,14.600000,14.600000,14.600000,14.600000,14.600000,0,2017-08-22
|
||||||
|
2016-11-10,14.560000,14.560000,14.560000,14.560000,14.560000,0,2017-08-22
|
||||||
|
2016-11-11,14.500000,14.500000,14.500000,14.500000,14.500000,0,2017-08-22
|
||||||
|
2016-11-14,14.510000,14.510000,14.510000,14.510000,14.510000,0,2017-08-22
|
||||||
|
2016-11-15,14.550000,14.550000,14.550000,14.550000,14.550000,0,2017-08-22
|
||||||
|
2016-11-16,14.510000,14.510000,14.510000,14.510000,14.510000,0,2017-08-22
|
||||||
|
2016-11-17,14.580000,14.580000,14.580000,14.580000,14.580000,0,2017-08-22
|
||||||
|
2016-11-18,14.560000,14.560000,14.560000,14.560000,14.560000,0,2017-08-22
|
||||||
|
2016-11-21,14.550000,14.550000,14.550000,14.550000,14.550000,0,2017-08-22
|
||||||
|
2016-11-22,14.450000,14.450000,14.450000,14.450000,14.450000,0,2017-08-22
|
||||||
|
2016-11-23,14.460000,14.460000,14.460000,14.460000,14.460000,0,2017-08-22
|
||||||
|
2016-11-25,14.440000,14.440000,14.440000,14.440000,14.440000,0,2017-08-22
|
||||||
|
2016-11-28,14.380000,14.380000,14.380000,14.380000,14.380000,0,2017-08-22
|
||||||
|
2016-11-29,14.420000,14.420000,14.420000,14.420000,14.420000,0,2017-08-22
|
||||||
|
2016-11-30,14.510000,14.510000,14.510000,14.510000,14.510000,0,2017-08-22
|
||||||
|
2016-12-01,14.510000,14.510000,14.510000,14.510000,14.510000,0,2017-08-22
|
||||||
|
2016-12-02,14.500000,14.500000,14.500000,14.500000,14.500000,0,2017-08-22
|
||||||
|
2016-12-05,14.490000,14.490000,14.490000,14.490000,14.490000,0,2017-08-22
|
||||||
|
2016-12-06,14.480000,14.480000,14.480000,14.480000,14.480000,0,2017-08-22
|
||||||
|
2016-12-07,14.420000,14.420000,14.420000,14.420000,14.420000,0,2017-08-22
|
||||||
|
2016-12-08,14.440000,14.440000,14.440000,14.440000,14.440000,0,2017-08-22
|
||||||
|
2016-12-09,14.420000,14.420000,14.420000,14.420000,14.420000,0,2017-08-22
|
||||||
|
2016-12-12,14.350000,14.350000,14.350000,14.350000,14.350000,0,2017-08-22
|
||||||
|
2016-12-13,14.390000,14.390000,14.390000,14.390000,14.390000,0,2017-08-22
|
||||||
|
2016-12-14,14.440000,14.440000,14.440000,14.440000,14.440000,0,2017-08-22
|
||||||
|
2016-12-15,14.440000,14.440000,14.440000,14.440000,14.440000,0,2017-08-22
|
||||||
|
2016-12-16,14.410000,14.410000,14.410000,14.410000,14.410000,0,2017-08-22
|
||||||
|
2016-12-19,14.390000,14.390000,14.390000,14.390000,14.390000,0,2017-08-22
|
||||||
|
2016-12-20,14.380000,14.380000,14.380000,14.380000,14.380000,0,2017-08-22
|
||||||
|
2016-12-21,14.390000,14.390000,14.390000,14.390000,14.390000,0,2017-08-22
|
||||||
|
2016-12-22,14.400000,14.400000,14.400000,14.400000,14.400000,0,2017-08-22
|
||||||
|
2016-12-23,14.400000,14.400000,14.400000,14.400000,14.400000,0,2017-08-22
|
||||||
|
2016-12-27,14.390000,14.390000,14.390000,14.390000,14.390000,0,2017-08-22
|
||||||
|
2016-12-28,14.390000,14.390000,14.390000,14.390000,14.390000,0,2017-08-22
|
||||||
|
2016-12-29,14.400000,14.400000,14.400000,14.400000,14.400000,0,2017-08-22
|
||||||
|
2016-12-30,14.380000,14.380000,14.380000,14.380000,14.380000,0,2017-08-22
|
||||||
|
2017-01-03,14.360000,14.360000,14.360000,14.360000,14.360000,0,2017-08-22
|
||||||
|
2017-01-04,14.330000,14.330000,14.330000,14.330000,14.330000,0,2017-08-22
|
||||||
|
2017-01-05,14.370000,14.370000,14.370000,14.370000,14.370000,0,2017-08-22
|
||||||
|
2017-01-06,14.330000,14.330000,14.330000,14.330000,14.330000,0,2017-08-22
|
||||||
|
2017-01-09,14.360000,14.360000,14.360000,14.360000,14.360000,0,2017-08-22
|
||||||
|
2017-01-10,14.350000,14.350000,14.350000,14.350000,14.350000,0,2017-08-22
|
||||||
|
2017-01-11,14.420000,14.420000,14.420000,14.420000,14.420000,0,2017-08-22
|
||||||
|
2017-01-12,14.370000,14.370000,14.370000,14.370000,14.370000,0,2017-08-22
|
||||||
|
2017-01-13,14.430000,14.430000,14.430000,14.430000,14.430000,0,2017-08-22
|
||||||
|
2017-01-17,14.390000,14.390000,14.390000,14.390000,14.390000,0,2017-08-22
|
||||||
|
2017-01-18,14.420000,14.420000,14.420000,14.420000,14.420000,0,2017-08-22
|
||||||
|
2017-01-19,14.430000,14.430000,14.430000,14.430000,14.430000,0,2017-08-22
|
||||||
|
2017-01-20,14.470000,14.470000,14.470000,14.470000,14.470000,0,2017-08-22
|
||||||
|
2017-01-23,14.470000,14.470000,14.470000,14.470000,14.470000,0,2017-08-22
|
||||||
|
2017-01-24,14.430000,14.430000,14.430000,14.430000,14.430000,0,2017-08-22
|
||||||
|
2017-01-25,14.450000,14.450000,14.450000,14.450000,14.450000,0,2017-08-22
|
||||||
|
2017-01-26,14.490000,14.490000,14.490000,14.490000,14.490000,0,2017-08-22
|
||||||
|
2017-01-27,14.480000,14.480000,14.480000,14.480000,14.480000,0,2017-08-22
|
||||||
|
2017-01-30,14.440000,14.440000,14.440000,14.440000,14.440000,0,2017-08-22
|
||||||
|
2017-01-31,14.420000,14.420000,14.420000,14.420000,14.420000,0,2017-08-22
|
||||||
|
2017-02-01,14.440000,14.440000,14.440000,14.440000,14.440000,0,2017-08-22
|
||||||
|
2017-02-02,14.450000,14.450000,14.450000,14.450000,14.450000,0,2017-08-22
|
||||||
|
2017-02-03,14.430000,14.430000,14.430000,14.430000,14.430000,0,2017-08-22
|
||||||
|
2017-02-06,14.390000,14.390000,14.390000,14.390000,14.390000,0,2017-08-22
|
||||||
|
2017-02-07,14.390000,14.390000,14.390000,14.390000,14.390000,0,2017-08-22
|
||||||
|
2017-02-08,14.330000,14.330000,14.330000,14.330000,14.330000,0,2017-08-22
|
||||||
|
2017-02-09,14.340000,14.340000,14.340000,14.340000,14.340000,0,2017-08-22
|
||||||
|
2017-02-10,14.300000,14.300000,14.300000,14.300000,14.300000,0,2017-08-22
|
||||||
|
2017-02-13,14.310000,14.310000,14.310000,14.310000,14.310000,0,2017-08-22
|
||||||
|
2017-02-14,14.300000,14.300000,14.300000,14.300000,14.300000,0,2017-08-22
|
||||||
|
2017-02-15,14.280000,14.280000,14.280000,14.280000,14.280000,0,2017-08-22
|
||||||
|
2017-02-16,14.200000,14.200000,14.200000,14.200000,14.200000,0,2017-08-22
|
||||||
|
2017-02-17,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-02-21,14.170000,14.170000,14.170000,14.170000,14.170000,0,2017-08-22
|
||||||
|
2017-02-22,14.160000,14.160000,14.160000,14.160000,14.160000,0,2017-08-22
|
||||||
|
2017-02-23,14.120000,14.120000,14.120000,14.120000,14.120000,0,2017-08-22
|
||||||
|
2017-02-24,14.090000,14.090000,14.090000,14.090000,14.090000,0,2017-08-22
|
||||||
|
2017-02-27,14.110000,14.110000,14.110000,14.110000,14.110000,0,2017-08-22
|
||||||
|
2017-02-28,14.140000,14.140000,14.140000,14.140000,14.140000,0,2017-08-22
|
||||||
|
2017-03-01,14.110000,14.110000,14.110000,14.110000,14.110000,0,2017-08-22
|
||||||
|
2017-03-02,14.080000,14.080000,14.080000,14.080000,14.080000,0,2017-08-22
|
||||||
|
2017-03-03,14.120000,14.120000,14.120000,14.120000,14.120000,0,2017-08-22
|
||||||
|
2017-03-06,14.120000,14.120000,14.120000,14.120000,14.120000,0,2017-08-22
|
||||||
|
2017-03-07,14.120000,14.120000,14.120000,14.120000,14.120000,0,2017-08-22
|
||||||
|
2017-03-08,14.060000,14.060000,14.060000,14.060000,14.060000,0,2017-08-22
|
||||||
|
2017-03-09,14.090000,14.090000,14.090000,14.090000,14.090000,0,2017-08-22
|
||||||
|
2017-03-10,14.090000,14.090000,14.090000,14.090000,14.090000,0,2017-08-22
|
||||||
|
2017-03-13,14.180000,14.180000,14.180000,14.180000,14.180000,0,2017-08-22
|
||||||
|
2017-03-14,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-03-15,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-03-16,14.120000,14.120000,14.120000,14.120000,14.120000,0,2017-08-22
|
||||||
|
2017-03-17,14.130000,14.130000,14.130000,14.130000,14.130000,0,2017-08-22
|
||||||
|
2017-03-20,14.100000,14.100000,14.100000,14.100000,14.100000,0,2017-08-22
|
||||||
|
2017-03-21,14.020000,14.020000,14.020000,14.020000,14.020000,0,2017-08-22
|
||||||
|
2017-03-22,14.020000,14.020000,14.020000,14.020000,14.020000,0,2017-08-22
|
||||||
|
2017-03-23,14.030000,14.030000,14.030000,14.030000,14.030000,0,2017-08-22
|
||||||
|
2017-03-24,14.030000,14.030000,14.030000,14.030000,14.030000,0,2017-08-22
|
||||||
|
2017-03-27,14.060000,14.060000,14.060000,14.060000,14.060000,0,2017-08-22
|
||||||
|
2017-03-28,14.100000,14.100000,14.100000,14.100000,14.100000,0,2017-08-22
|
||||||
|
2017-03-29,14.110000,14.110000,14.110000,14.110000,14.110000,0,2017-08-22
|
||||||
|
2017-03-30,14.120000,14.120000,14.120000,14.120000,14.120000,0,2017-08-22
|
||||||
|
2017-03-31,14.120000,14.120000,14.120000,14.120000,14.120000,0,2017-08-22
|
||||||
|
2017-04-03,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-04-04,14.200000,14.200000,14.200000,14.200000,14.200000,0,2017-08-22
|
||||||
|
2017-04-05,14.180000,14.180000,14.180000,14.180000,14.180000,0,2017-08-22
|
||||||
|
2017-04-06,14.210000,14.210000,14.210000,14.210000,14.210000,0,2017-08-22
|
||||||
|
2017-04-07,14.220000,14.220000,14.220000,14.220000,14.220000,0,2017-08-22
|
||||||
|
2017-04-10,14.170000,14.170000,14.170000,14.170000,14.170000,0,2017-08-22
|
||||||
|
2017-04-11,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-04-12,14.130000,14.130000,14.130000,14.130000,14.130000,0,2017-08-22
|
||||||
|
2017-04-13,14.100000,14.100000,14.100000,14.100000,14.100000,0,2017-08-22
|
||||||
|
2017-04-17,14.080000,14.080000,14.080000,14.080000,14.080000,0,2017-08-22
|
||||||
|
2017-04-18,14.060000,14.060000,14.060000,14.060000,14.060000,0,2017-08-22
|
||||||
|
2017-04-19,14.010000,14.010000,14.010000,14.010000,14.010000,0,2017-08-22
|
||||||
|
2017-04-20,14.030000,14.030000,14.030000,14.030000,14.030000,0,2017-08-22
|
||||||
|
2017-04-21,14.000000,14.000000,14.000000,14.000000,14.000000,0,2017-08-22
|
||||||
|
2017-04-24,14.050000,14.050000,14.050000,14.050000,14.050000,0,2017-08-22
|
||||||
|
2017-04-25,14.090000,14.090000,14.090000,14.090000,14.090000,0,2017-08-22
|
||||||
|
2017-04-26,14.090000,14.090000,14.090000,14.090000,14.090000,0,2017-08-22
|
||||||
|
2017-04-27,14.070000,14.070000,14.070000,14.070000,14.070000,0,2017-08-22
|
||||||
|
2017-04-28,14.040000,14.040000,14.040000,14.040000,14.040000,0,2017-08-22
|
||||||
|
2017-05-01,14.080000,14.080000,14.080000,14.080000,14.080000,0,2017-08-22
|
||||||
|
2017-05-02,14.090000,14.090000,14.090000,14.090000,14.090000,0,2017-08-22
|
||||||
|
2017-05-03,14.110000,14.110000,14.110000,14.110000,14.110000,0,2017-08-22
|
||||||
|
2017-05-04,14.080000,14.080000,14.080000,14.080000,14.080000,0,2017-08-22
|
||||||
|
2017-05-05,14.060000,14.060000,14.060000,14.060000,14.060000,0,2017-08-22
|
||||||
|
2017-05-08,14.040000,14.040000,14.040000,14.040000,14.040000,0,2017-08-22
|
||||||
|
2017-05-09,14.000000,14.000000,14.000000,14.000000,14.000000,0,2017-08-22
|
||||||
|
2017-05-10,14.000000,14.000000,14.000000,14.000000,14.000000,0,2017-08-22
|
||||||
|
2017-05-11,14.020000,14.020000,14.020000,14.020000,14.020000,0,2017-08-22
|
||||||
|
2017-05-12,14.040000,14.040000,14.040000,14.040000,14.040000,0,2017-08-22
|
||||||
|
2017-05-15,14.060000,14.060000,14.060000,14.060000,14.060000,0,2017-08-22
|
||||||
|
2017-05-16,14.090000,14.090000,14.090000,14.090000,14.090000,0,2017-08-22
|
||||||
|
2017-05-17,13.970000,13.970000,13.970000,13.970000,13.970000,0,2017-08-22
|
||||||
|
2017-05-18,14.030000,14.030000,14.030000,14.030000,14.030000,0,2017-08-22
|
||||||
|
2017-05-19,14.050000,14.050000,14.050000,14.050000,14.050000,0,2017-08-22
|
||||||
|
2017-05-22,14.090000,14.090000,14.090000,14.090000,14.090000,0,2017-08-22
|
||||||
|
2017-05-23,14.140000,14.140000,14.140000,14.140000,14.140000,0,2017-08-22
|
||||||
|
2017-05-24,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-05-25,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-05-26,14.190000,14.190000,14.190000,14.190000,14.190000,0,2017-08-22
|
||||||
|
2017-05-30,14.130000,14.130000,14.130000,14.130000,14.130000,0,2017-08-22
|
||||||
|
2017-05-31,14.090000,14.090000,14.090000,14.090000,14.090000,0,2017-08-22
|
||||||
|
2017-06-01,14.060000,14.060000,14.060000,14.060000,14.060000,0,2017-08-22
|
||||||
|
2017-06-02,14.090000,14.090000,14.090000,14.090000,14.090000,0,2017-08-22
|
||||||
|
2017-06-05,14.100000,14.100000,14.100000,14.100000,14.100000,0,2017-08-22
|
||||||
|
2017-06-06,14.130000,14.130000,14.130000,14.130000,14.130000,0,2017-08-22
|
||||||
|
2017-06-07,14.190000,14.190000,14.190000,14.190000,14.190000,0,2017-08-22
|
||||||
|
2017-06-08,14.230000,14.230000,14.230000,14.230000,14.230000,0,2017-08-22
|
||||||
|
2017-06-09,14.120000,14.120000,14.120000,14.120000,14.120000,0,2017-08-22
|
||||||
|
2017-06-12,14.010000,14.010000,14.010000,14.010000,14.010000,0,2017-08-22
|
||||||
|
2017-06-13,14.060000,14.060000,14.060000,14.060000,14.060000,0,2017-08-22
|
||||||
|
2017-06-14,14.050000,14.050000,14.050000,14.050000,14.050000,0,2017-08-22
|
||||||
|
2017-06-15,14.040000,14.040000,14.040000,14.040000,14.040000,0,2017-08-22
|
||||||
|
2017-06-16,14.030000,14.030000,14.030000,14.030000,14.030000,0,2017-08-22
|
||||||
|
2017-06-19,14.100000,14.100000,14.100000,14.100000,14.100000,0,2017-08-22
|
||||||
|
2017-06-20,14.120000,14.120000,14.120000,14.120000,14.120000,0,2017-08-22
|
||||||
|
2017-06-21,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-06-22,14.120000,14.120000,14.120000,14.120000,14.120000,0,2017-08-22
|
||||||
|
2017-06-23,14.100000,14.100000,14.100000,14.100000,14.100000,0,2017-08-22
|
||||||
|
2017-06-26,14.040000,14.040000,14.040000,14.040000,14.040000,0,2017-08-22
|
||||||
|
2017-06-27,14.000000,14.000000,14.000000,14.000000,14.000000,0,2017-08-22
|
||||||
|
2017-06-28,14.050000,14.050000,14.050000,14.050000,14.050000,0,2017-08-22
|
||||||
|
2017-06-29,13.980000,13.980000,13.980000,13.980000,13.980000,0,2017-08-22
|
||||||
|
2017-06-30,13.960000,13.960000,13.960000,13.960000,13.960000,0,2017-08-22
|
||||||
|
2017-07-03,13.910000,13.910000,13.910000,13.910000,13.910000,0,2017-08-22
|
||||||
|
2017-07-05,14.040000,14.040000,14.040000,14.040000,14.040000,0,2017-08-22
|
||||||
|
2017-07-06,14.090000,14.090000,14.090000,14.090000,14.090000,0,2017-08-22
|
||||||
|
2017-07-07,14.110000,14.110000,14.110000,14.110000,14.110000,0,2017-08-22
|
||||||
|
2017-07-10,14.120000,14.120000,14.120000,14.120000,14.120000,0,2017-08-22
|
||||||
|
2017-07-11,14.130000,14.130000,14.130000,14.130000,14.130000,0,2017-08-22
|
||||||
|
2017-07-12,14.170000,14.170000,14.170000,14.170000,14.170000,0,2017-08-22
|
||||||
|
2017-07-13,14.140000,14.140000,14.140000,14.140000,14.140000,0,2017-08-22
|
||||||
|
2017-07-14,14.130000,14.130000,14.130000,14.130000,14.130000,0,2017-08-22
|
||||||
|
2017-07-17,14.090000,14.090000,14.090000,14.090000,14.090000,0,2017-08-22
|
||||||
|
2017-07-18,14.120000,14.120000,14.120000,14.120000,14.120000,0,2017-08-22
|
||||||
|
2017-07-19,14.170000,14.170000,14.170000,14.170000,14.170000,0,2017-08-22
|
||||||
|
2017-07-20,14.170000,14.170000,14.170000,14.170000,14.170000,0,2017-08-22
|
||||||
|
2017-07-21,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-07-24,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-07-25,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-07-26,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-07-27,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-07-28,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-07-31,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-08-01,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-08-02,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-08-03,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-08-04,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-08-07,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-08-08,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-08-09,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-08-10,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-08-11,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-08-14,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-08-15,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-08-16,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-08-17,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-08-18,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-08-21,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-22
|
||||||
|
2017-08-22,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-24 08:26:38
|
||||||
|
2017-08-23,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-24 08:26:38
|
||||||
|
2017-08-24,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-25 07:50:50
|
||||||
|
2017-08-25,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-26 07:47:11
|
||||||
|
2017-08-28,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-29 07:18:44
|
||||||
|
2017-08-29,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-29 22:27:18
|
||||||
|
2017-08-30,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-08-30 21:26:47
|
||||||
|
2017-08-31,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-09-01 08:18:04
|
||||||
|
2017-09-01,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-09-05 07:48:27
|
||||||
|
2017-09-05,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-09-06 07:03:16
|
||||||
|
2017-09-06,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-09-07 07:38:19
|
||||||
|
2017-09-07,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-09-08 07:09:10
|
||||||
|
2017-09-08,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-09-09 08:43:50
|
||||||
|
2017-09-11,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-09-13 06:44:33
|
||||||
|
2017-09-12,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-09-13 14:29:06
|
||||||
|
2017-09-13,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-09-15 07:54:07
|
||||||
|
2017-09-14,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-09-15 07:54:07
|
||||||
|
2017-09-15,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-09-18 07:57:00
|
||||||
|
2017-09-18,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-09-19 07:04:50
|
||||||
|
2017-09-19,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-09-20 07:02:59
|
||||||
|
2017-09-20,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-09-21 06:52:01
|
||||||
|
2017-09-21,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-09-22 07:46:25
|
||||||
|
2017-09-22,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-09-23 08:05:02
|
||||||
|
2017-09-25,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-09-26 07:33:50
|
||||||
|
2017-09-26,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-09-27 07:38:44
|
||||||
|
2017-09-27,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-09-28 06:48:39
|
||||||
|
2017-09-28,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-09-29 08:00:20
|
||||||
|
2017-09-29,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-04 07:54:54
|
||||||
|
2017-10-02,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-04 07:54:54
|
||||||
|
2017-10-03,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-04 07:54:54
|
||||||
|
2017-10-04,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-05 07:13:33
|
||||||
|
2017-10-05,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-06 06:58:57
|
||||||
|
2017-10-06,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-09 07:35:40
|
||||||
|
2017-10-09,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-10 07:30:35
|
||||||
|
2017-10-10,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-11 07:10:33
|
||||||
|
2017-10-11,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-12 07:02:18
|
||||||
|
2017-10-12,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-13 07:44:41
|
||||||
|
2017-10-13,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-15 21:31:35
|
||||||
|
2017-10-16,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-17 07:24:53
|
||||||
|
2017-10-17,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-18 06:38:28
|
||||||
|
2017-10-18,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-19 07:41:01
|
||||||
|
2017-10-19,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-20 07:48:13
|
||||||
|
2017-10-20,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-23 07:36:15
|
||||||
|
2017-10-23,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-24 07:44:32
|
||||||
|
2017-10-24,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-26 06:30:50
|
||||||
|
2017-10-25,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-26 06:30:50
|
||||||
|
2017-10-26,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-31 08:26:49
|
||||||
|
2017-10-27,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-31 08:26:49
|
||||||
|
2017-10-30,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-10-31 08:26:49
|
||||||
|
2017-10-31,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-01 07:49:35
|
||||||
|
2017-11-01,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-07 10:58:03
|
||||||
|
2017-11-02,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-07 10:58:03
|
||||||
|
2017-11-03,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-07 10:58:03
|
||||||
|
2017-11-06,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-07 10:58:03
|
||||||
|
2017-11-07,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-08 07:52:27
|
||||||
|
2017-11-08,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-15 07:55:39
|
||||||
|
2017-11-09,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-15 07:55:39
|
||||||
|
2017-11-10,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-15 07:55:39
|
||||||
|
2017-11-13,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-15 07:55:39
|
||||||
|
2017-11-14,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-15 07:55:39
|
||||||
|
2017-11-15,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-20 07:43:46
|
||||||
|
2017-11-16,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-20 07:43:46
|
||||||
|
2017-11-17,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-20 07:43:46
|
||||||
|
2017-11-20,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-28 13:58:38
|
||||||
|
2017-11-21,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-28 13:58:38
|
||||||
|
2017-11-22,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-28 13:58:38
|
||||||
|
2017-11-24,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-28 13:58:38
|
||||||
|
2017-11-27,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-28 13:58:38
|
||||||
|
2017-11-28,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-30 07:17:01
|
||||||
|
2017-11-29,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-11-30 07:17:01
|
||||||
|
2017-11-30,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-12-02 19:04:46
|
||||||
|
2017-12-01,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-12-02 19:04:46
|
||||||
|
2017-12-04,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-12-06 14:41:27
|
||||||
|
2017-12-05,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-12-06 14:41:27
|
||||||
|
2017-12-06,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-12-11 20:07:47
|
||||||
|
2017-12-07,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-12-11 20:07:47
|
||||||
|
2017-12-08,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-12-11 20:07:47
|
||||||
|
2017-12-11,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-12-12 07:18:16
|
||||||
|
2017-12-12,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-12-13 10:46:22
|
||||||
|
2017-12-13,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-12-14 07:15:00
|
||||||
|
2017-12-14,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-12-15 07:46:46
|
||||||
|
2017-12-15,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-12-19 07:11:54
|
||||||
|
2017-12-18,14.150000,14.150000,14.150000,14.150000,14.150000,0,2017-12-19 07:11:54
|
||||||
|
7
overrides/frozen/adusx.json
Normal file
7
overrides/frozen/adusx.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"symbol": "adusx",
|
||||||
|
"longName": "?",
|
||||||
|
"freeze_date": "2017-12-18",
|
||||||
|
"created": "2026-08-31",
|
||||||
|
"reason": "yahoo-empty"
|
||||||
|
}
|
||||||
5
overrides/frozen/aectx-capitalGain.csv
Normal file
5
overrides/frozen/aectx-capitalGain.csv
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
Date,Capital Gains
|
||||||
|
2021-12-21,1.204000
|
||||||
|
2017-12-19,0.016000
|
||||||
|
2018-12-18,0.414000
|
||||||
|
2020-12-22,0.608000
|
||||||
|
10
overrides/frozen/aectx-dividend.csv
Normal file
10
overrides/frozen/aectx-dividend.csv
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
Date,Dividends
|
||||||
|
2019-12-17,0.092000
|
||||||
|
2020-12-22,0.608000
|
||||||
|
2022-12-21,0.291000
|
||||||
|
2024-12-17,0.052000
|
||||||
|
2016-12-20,0.124000
|
||||||
|
2017-12-19,0.206000
|
||||||
|
2018-12-18,0.414000
|
||||||
|
2021-12-21,1.276000
|
||||||
|
2024-03-19,0.164000
|
||||||
|
2
overrides/frozen/aectx-history.csv
Normal file
2
overrides/frozen/aectx-history.csv
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
Date,Open,High,Low,Close,Adj Close,Volume
|
||||||
|
2025-09-23,14.420000,14.420000,14.420000,14.420000,14.420000,0
|
||||||
|
7
overrides/frozen/aectx.json
Normal file
7
overrides/frozen/aectx.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"symbol": "aectx",
|
||||||
|
"longName": "American Century World Mutual Funds, Inc. - Emerging Markets Small Cap Fund",
|
||||||
|
"freeze_date": "2025-09-23",
|
||||||
|
"created": "2026-08-31",
|
||||||
|
"reason": "yahoo-empty"
|
||||||
|
}
|
||||||
478
overrides/frozen/afxpx-dividend.csv
Normal file
478
overrides/frozen/afxpx-dividend.csv
Normal file
|
|
@ -0,0 +1,478 @@
|
||||||
|
Date,Dividends,ctime
|
||||||
|
2013-04-01,0.007,2017-08-22
|
||||||
|
2017-07-03,0.014,2017-08-22
|
||||||
|
2014-08-01,0.012,2017-08-22
|
||||||
|
2017-01-03,0.014,2017-08-22
|
||||||
|
2014-02-03,0.007,2017-08-22
|
||||||
|
2013-07-01,0.031,2017-08-22
|
||||||
|
2013-01-02,0.007,2017-08-22
|
||||||
|
2012-06-01,0.013,2017-08-22
|
||||||
|
2015-12-22,0.22,2017-08-22
|
||||||
|
2013-10-01,0.007,2017-08-22
|
||||||
|
2014-12-01,0.009,2017-08-22
|
||||||
|
2011-12-30,0.004,2017-08-22
|
||||||
|
2016-06-01,0.016,2017-08-22
|
||||||
|
2015-05-01,0.005,2017-08-22
|
||||||
|
2015-03-02,0.004,2017-08-22
|
||||||
|
2012-09-04,0.036,2017-08-22
|
||||||
|
2012-04-02,0.016,2017-08-22
|
||||||
|
2013-08-01,0.025,2017-08-22
|
||||||
|
2016-04-01,0.014,2017-08-22
|
||||||
|
2012-03-01,0.057,2017-08-22
|
||||||
|
2015-02-02,0.006,2017-08-22
|
||||||
|
2016-12-01,0.014,2017-08-22
|
||||||
|
2012-07-02,0.038,2017-08-22
|
||||||
|
2016-10-03,0.013,2017-08-22
|
||||||
|
2013-11-01,0.009,2017-08-22
|
||||||
|
2014-01-02,0.007,2017-08-22
|
||||||
|
2016-07-01,0.028,2017-08-22
|
||||||
|
2012-10-01,0.046,2017-08-22
|
||||||
|
2015-06-01,0.01,2017-08-22
|
||||||
|
2015-12-01,0.013,2017-08-22
|
||||||
|
2014-05-01,0.01,2017-08-22
|
||||||
|
2017-04-03,0.018,2017-08-22
|
||||||
|
2012-12-20,0.137,2017-08-22
|
||||||
|
2015-09-01,0.005,2017-08-22
|
||||||
|
2016-03-01,0.013,2017-08-22
|
||||||
|
2011-11-30,0.003,2017-08-22
|
||||||
|
2014-11-03,0.011,2017-08-22
|
||||||
|
2016-11-01,0.013,2017-08-22
|
||||||
|
2012-08-01,0.023,2017-08-22
|
||||||
|
2015-04-01,0.004,2017-08-22
|
||||||
|
2012-05-01,0.006,2017-08-22
|
||||||
|
2016-02-01,0.013,2017-08-22
|
||||||
|
2016-08-01,0.016,2017-08-22
|
||||||
|
2015-07-01,0.024,2017-08-22
|
||||||
|
2015-01-02,0.02,2017-08-22
|
||||||
|
2012-01-31,0.004,2017-08-22
|
||||||
|
2012-12-03,0.018,2017-08-22
|
||||||
|
2014-06-02,0.013,2017-08-22
|
||||||
|
2015-10-01,0.014,2017-08-22
|
||||||
|
2013-03-01,0.004,2017-08-22
|
||||||
|
2017-08-01,0.025,2017-08-22
|
||||||
|
2013-05-01,0.009,2017-08-22
|
||||||
|
2013-12-20,0.069,2017-08-22
|
||||||
|
2014-09-02,0.015,2017-08-22
|
||||||
|
2017-03-01,0.013,2017-08-22
|
||||||
|
2015-11-02,0.011,2017-08-22
|
||||||
|
2017-05-01,0.01,2017-08-22
|
||||||
|
2014-04-01,0.009,2017-08-22
|
||||||
|
2016-01-04,0.025,2017-08-22
|
||||||
|
2013-02-01,0.006,2017-08-22
|
||||||
|
2015-08-03,0.009,2017-08-22
|
||||||
|
2017-06-01,0.021,2017-08-22
|
||||||
|
2014-07-01,0.028,2017-08-22
|
||||||
|
2014-12-22,0.105,2017-08-22
|
||||||
|
2016-05-03,0.015,2017-08-22
|
||||||
|
2013-06-03,0.02,2017-08-22
|
||||||
|
2013-12-02,0.008,2017-08-22
|
||||||
|
2014-10-01,0.013,2017-08-22
|
||||||
|
2011-10-31,0.003,2017-08-22
|
||||||
|
2017-02-01,0.025,2017-08-22
|
||||||
|
2014-03-03,0.012,2017-08-22
|
||||||
|
2013-09-03,0.026,2017-08-22
|
||||||
|
2017-10-02,0.015,2017-10-10 07:30:35
|
||||||
|
2013-01-02,0.007,2017-10-20 09:54:16
|
||||||
|
2012-06-01,0.013,2017-10-20 09:54:16
|
||||||
|
2015-12-22,0.22,2017-10-20 09:54:16
|
||||||
|
2013-10-01,0.007,2017-10-20 09:54:16
|
||||||
|
2014-12-01,0.009,2017-10-20 09:54:16
|
||||||
|
2011-12-30,0.004,2017-10-20 09:54:16
|
||||||
|
2016-06-01,0.016,2017-10-20 09:54:16
|
||||||
|
2015-05-01,0.005,2017-10-20 09:54:16
|
||||||
|
2015-03-02,0.004,2017-10-20 09:54:16
|
||||||
|
2012-09-04,0.036,2017-10-20 09:54:16
|
||||||
|
2012-04-02,0.016,2017-10-20 09:54:16
|
||||||
|
2013-08-01,0.025,2017-10-20 09:54:16
|
||||||
|
2016-04-01,0.014,2017-10-20 09:54:16
|
||||||
|
2012-03-01,0.057,2017-10-20 09:54:16
|
||||||
|
2015-02-02,0.006,2017-10-20 09:54:16
|
||||||
|
2016-12-01,0.014,2017-10-20 09:54:16
|
||||||
|
2012-07-02,0.038,2017-10-20 09:54:16
|
||||||
|
2016-10-03,0.013,2017-10-20 09:54:16
|
||||||
|
2013-11-01,0.009,2017-10-20 09:54:16
|
||||||
|
2014-01-02,0.007,2017-10-20 09:54:16
|
||||||
|
2016-07-01,0.028,2017-10-20 09:54:16
|
||||||
|
2012-10-01,0.046,2017-10-20 09:54:16
|
||||||
|
2015-06-01,0.01,2017-10-20 09:54:16
|
||||||
|
2015-12-01,0.013,2017-10-20 09:54:16
|
||||||
|
2014-05-01,0.01,2017-10-20 09:54:16
|
||||||
|
2017-04-03,0.018,2017-10-20 09:54:16
|
||||||
|
2012-12-20,0.137,2017-10-20 09:54:16
|
||||||
|
2015-09-01,0.005,2017-10-20 09:54:16
|
||||||
|
2016-03-01,0.013,2017-10-20 09:54:16
|
||||||
|
2011-11-30,0.003,2017-10-20 09:54:16
|
||||||
|
2014-11-03,0.011,2017-10-20 09:54:16
|
||||||
|
2016-11-01,0.013,2017-10-20 09:54:16
|
||||||
|
2012-08-01,0.023,2017-10-20 09:54:16
|
||||||
|
2015-04-01,0.004,2017-10-20 09:54:16
|
||||||
|
2012-05-01,0.006,2017-10-20 09:54:16
|
||||||
|
2016-02-01,0.013,2017-10-20 09:54:16
|
||||||
|
2016-08-01,0.016,2017-10-20 09:54:16
|
||||||
|
2015-07-01,0.024,2017-10-20 09:54:16
|
||||||
|
2015-01-02,0.02,2017-10-20 09:54:16
|
||||||
|
2012-01-31,0.004,2017-10-20 09:54:16
|
||||||
|
2012-12-03,0.018,2017-10-20 09:54:16
|
||||||
|
2014-06-02,0.013,2017-10-20 09:54:16
|
||||||
|
2015-10-01,0.014,2017-10-20 09:54:16
|
||||||
|
2013-03-01,0.004,2017-10-20 09:54:16
|
||||||
|
2017-08-01,0.025,2017-10-20 09:54:16
|
||||||
|
2013-05-01,0.009,2017-10-20 09:54:16
|
||||||
|
2013-12-20,0.069,2017-10-20 09:54:16
|
||||||
|
2014-09-02,0.015,2017-10-20 09:54:16
|
||||||
|
2017-03-01,0.013,2017-10-20 09:54:16
|
||||||
|
2015-11-02,0.011,2017-10-20 09:54:16
|
||||||
|
2017-05-01,0.01,2017-10-20 09:54:16
|
||||||
|
2014-04-01,0.009,2017-10-20 09:54:16
|
||||||
|
2016-01-04,0.025,2017-10-20 09:54:16
|
||||||
|
2013-02-01,0.006,2017-10-20 09:54:16
|
||||||
|
2015-08-03,0.009,2017-10-20 09:54:16
|
||||||
|
2017-06-01,0.021,2017-10-20 09:54:16
|
||||||
|
2014-07-01,0.028,2017-10-20 09:54:16
|
||||||
|
2014-12-22,0.105,2017-10-20 09:54:16
|
||||||
|
2016-05-03,0.015,2017-10-20 09:54:16
|
||||||
|
2017-09-01,0.015,2017-10-20 09:54:16
|
||||||
|
2013-06-03,0.02,2017-10-20 09:54:16
|
||||||
|
2013-12-02,0.008,2017-10-20 09:54:16
|
||||||
|
2014-10-01,0.013,2017-10-20 09:54:16
|
||||||
|
2011-10-31,0.003,2017-10-20 09:54:16
|
||||||
|
2017-02-01,0.025,2017-10-20 09:54:16
|
||||||
|
2014-03-03,0.012,2017-10-20 09:54:16
|
||||||
|
2013-09-03,0.026,2017-10-20 09:54:16
|
||||||
|
2017-11-01,0.016,2017-11-15 07:55:39
|
||||||
|
2013-08-01,0.025,2017-11-15 07:55:39
|
||||||
|
2016-04-01,0.014,2017-11-15 07:55:39
|
||||||
|
2012-03-01,0.057,2017-11-15 07:55:39
|
||||||
|
2015-02-02,0.006,2017-11-15 07:55:39
|
||||||
|
2016-12-01,0.014,2017-11-15 07:55:39
|
||||||
|
2012-07-02,0.038,2017-11-15 07:55:39
|
||||||
|
2016-10-03,0.013,2017-11-15 07:55:39
|
||||||
|
2013-11-01,0.009,2017-11-15 07:55:39
|
||||||
|
2014-01-02,0.007,2017-11-15 07:55:39
|
||||||
|
2016-07-01,0.028,2017-11-15 07:55:39
|
||||||
|
2012-10-01,0.046,2017-11-15 07:55:39
|
||||||
|
2015-06-01,0.01,2017-11-15 07:55:39
|
||||||
|
2015-12-01,0.013,2017-11-15 07:55:39
|
||||||
|
2014-05-01,0.01,2017-11-15 07:55:39
|
||||||
|
2017-04-03,0.018,2017-11-15 07:55:39
|
||||||
|
2012-12-20,0.137,2017-11-15 07:55:39
|
||||||
|
2015-09-01,0.005,2017-11-15 07:55:39
|
||||||
|
2016-03-01,0.013,2017-11-15 07:55:39
|
||||||
|
2011-11-30,0.003,2017-11-15 07:55:39
|
||||||
|
2014-11-03,0.011,2017-11-15 07:55:39
|
||||||
|
2016-11-01,0.013,2017-11-15 07:55:39
|
||||||
|
2012-08-01,0.023,2017-11-15 07:55:39
|
||||||
|
2015-04-01,0.004,2017-11-15 07:55:39
|
||||||
|
2012-05-01,0.006,2017-11-15 07:55:39
|
||||||
|
2016-02-01,0.013,2017-11-15 07:55:39
|
||||||
|
2016-08-01,0.016,2017-11-15 07:55:39
|
||||||
|
2015-07-01,0.024,2017-11-15 07:55:39
|
||||||
|
2015-01-02,0.02,2017-11-15 07:55:39
|
||||||
|
2012-01-31,0.004,2017-11-15 07:55:39
|
||||||
|
2012-12-03,0.018,2017-11-15 07:55:39
|
||||||
|
2014-06-02,0.013,2017-11-15 07:55:39
|
||||||
|
2015-10-01,0.014,2017-11-15 07:55:39
|
||||||
|
2013-03-01,0.004,2017-11-15 07:55:39
|
||||||
|
2017-08-01,0.025,2017-11-15 07:55:39
|
||||||
|
2013-05-01,0.009,2017-11-15 07:55:39
|
||||||
|
2013-12-20,0.069,2017-11-15 07:55:39
|
||||||
|
2014-09-02,0.015,2017-11-15 07:55:39
|
||||||
|
2017-03-01,0.013,2017-11-15 07:55:39
|
||||||
|
2015-11-02,0.011,2017-11-15 07:55:39
|
||||||
|
2017-05-01,0.01,2017-11-15 07:55:39
|
||||||
|
2014-04-01,0.009,2017-11-15 07:55:39
|
||||||
|
2016-01-04,0.025,2017-11-15 07:55:39
|
||||||
|
2013-02-01,0.006,2017-11-15 07:55:39
|
||||||
|
2015-08-03,0.009,2017-11-15 07:55:39
|
||||||
|
2017-06-01,0.021,2017-11-15 07:55:39
|
||||||
|
2014-07-01,0.028,2017-11-15 07:55:39
|
||||||
|
2014-12-22,0.105,2017-11-15 07:55:39
|
||||||
|
2016-05-03,0.015,2017-11-15 07:55:39
|
||||||
|
2017-09-01,0.015,2017-11-15 07:55:39
|
||||||
|
2013-06-03,0.02,2017-11-15 07:55:39
|
||||||
|
2013-12-02,0.008,2017-11-15 07:55:39
|
||||||
|
2014-10-01,0.013,2017-11-15 07:55:39
|
||||||
|
2011-10-31,0.003,2017-11-15 07:55:39
|
||||||
|
2017-02-01,0.025,2017-11-15 07:55:39
|
||||||
|
2014-03-03,0.012,2017-11-15 07:55:39
|
||||||
|
2013-09-03,0.026,2017-11-15 07:55:39
|
||||||
|
2017-12-01,0.017,2017-12-11 20:07:47
|
||||||
|
2015-07-01,0.024,2017-12-11 20:07:47
|
||||||
|
2015-01-02,0.02,2017-12-11 20:07:47
|
||||||
|
2012-01-31,0.004,2017-12-11 20:07:47
|
||||||
|
2012-12-03,0.018,2017-12-11 20:07:47
|
||||||
|
2014-06-02,0.013,2017-12-11 20:07:47
|
||||||
|
2015-10-01,0.014,2017-12-11 20:07:47
|
||||||
|
2013-03-01,0.004,2017-12-11 20:07:47
|
||||||
|
2017-08-01,0.025,2017-12-11 20:07:47
|
||||||
|
2013-05-01,0.009,2017-12-11 20:07:47
|
||||||
|
2013-12-20,0.069,2017-12-11 20:07:47
|
||||||
|
2014-09-02,0.015,2017-12-11 20:07:47
|
||||||
|
2017-03-01,0.013,2017-12-11 20:07:47
|
||||||
|
2015-11-02,0.011,2017-12-11 20:07:47
|
||||||
|
2017-05-01,0.01,2017-12-11 20:07:47
|
||||||
|
2014-04-01,0.009,2017-12-11 20:07:47
|
||||||
|
2016-01-04,0.025,2017-12-11 20:07:47
|
||||||
|
2013-02-01,0.006,2017-12-11 20:07:47
|
||||||
|
2015-08-03,0.009,2017-12-11 20:07:47
|
||||||
|
2017-06-01,0.021,2017-12-11 20:07:47
|
||||||
|
2014-07-01,0.028,2017-12-11 20:07:47
|
||||||
|
2014-12-22,0.105,2017-12-11 20:07:47
|
||||||
|
2016-05-03,0.015,2017-12-11 20:07:47
|
||||||
|
2017-09-01,0.015,2017-12-11 20:07:47
|
||||||
|
2013-06-03,0.02,2017-12-11 20:07:47
|
||||||
|
2013-12-02,0.008,2017-12-11 20:07:47
|
||||||
|
2014-10-01,0.013,2017-12-11 20:07:47
|
||||||
|
2011-10-31,0.003,2017-12-11 20:07:47
|
||||||
|
2017-02-01,0.025,2017-12-11 20:07:47
|
||||||
|
2014-03-03,0.012,2017-12-11 20:07:47
|
||||||
|
2013-09-03,0.026,2017-12-11 20:07:47
|
||||||
|
2018-01-02,0.023,2018-01-16 07:54:11
|
||||||
|
2016-04-01,0.014,2018-01-16 07:54:11
|
||||||
|
2012-03-01,0.057,2018-01-16 07:54:11
|
||||||
|
2015-02-02,0.006,2018-01-16 07:54:11
|
||||||
|
2016-12-01,0.014,2018-01-16 07:54:11
|
||||||
|
2012-07-02,0.038,2018-01-16 07:54:11
|
||||||
|
2016-10-03,0.013,2018-01-16 07:54:11
|
||||||
|
2013-11-01,0.009,2018-01-16 07:54:11
|
||||||
|
2014-01-02,0.007,2018-01-16 07:54:11
|
||||||
|
2016-07-01,0.028,2018-01-16 07:54:11
|
||||||
|
2012-10-01,0.046,2018-01-16 07:54:11
|
||||||
|
2015-06-01,0.01,2018-01-16 07:54:11
|
||||||
|
2015-12-01,0.013,2018-01-16 07:54:11
|
||||||
|
2014-05-01,0.01,2018-01-16 07:54:11
|
||||||
|
2017-04-03,0.018,2018-01-16 07:54:11
|
||||||
|
2012-12-20,0.137,2018-01-16 07:54:11
|
||||||
|
2015-09-01,0.005,2018-01-16 07:54:11
|
||||||
|
2016-03-01,0.013,2018-01-16 07:54:11
|
||||||
|
2011-11-30,0.003,2018-01-16 07:54:11
|
||||||
|
2014-11-03,0.011,2018-01-16 07:54:11
|
||||||
|
2016-11-01,0.013,2018-01-16 07:54:11
|
||||||
|
2012-08-01,0.023,2018-01-16 07:54:11
|
||||||
|
2015-04-01,0.004,2018-01-16 07:54:11
|
||||||
|
2012-05-01,0.006,2018-01-16 07:54:11
|
||||||
|
2016-02-01,0.013,2018-01-16 07:54:11
|
||||||
|
2016-08-01,0.016,2018-01-16 07:54:11
|
||||||
|
2017-12-01,0.017,2018-01-16 07:54:11
|
||||||
|
2015-07-01,0.024,2018-01-16 07:54:11
|
||||||
|
2015-01-02,0.02,2018-01-16 07:54:11
|
||||||
|
2012-01-31,0.004,2018-01-16 07:54:11
|
||||||
|
2012-12-03,0.018,2018-01-16 07:54:11
|
||||||
|
2014-06-02,0.013,2018-01-16 07:54:11
|
||||||
|
2015-10-01,0.014,2018-01-16 07:54:11
|
||||||
|
2013-03-01,0.004,2018-01-16 07:54:11
|
||||||
|
2017-08-01,0.025,2018-01-16 07:54:11
|
||||||
|
2013-05-01,0.009,2018-01-16 07:54:11
|
||||||
|
2013-12-20,0.069,2018-01-16 07:54:11
|
||||||
|
2014-09-02,0.015,2018-01-16 07:54:11
|
||||||
|
2017-03-01,0.013,2018-01-16 07:54:11
|
||||||
|
2015-11-02,0.011,2018-01-16 07:54:11
|
||||||
|
2017-05-01,0.01,2018-01-16 07:54:11
|
||||||
|
2014-04-01,0.009,2018-01-16 07:54:11
|
||||||
|
2016-01-04,0.025,2018-01-16 07:54:11
|
||||||
|
2013-02-01,0.006,2018-01-16 07:54:11
|
||||||
|
2015-08-03,0.009,2018-01-16 07:54:11
|
||||||
|
2017-06-01,0.021,2018-01-16 07:54:11
|
||||||
|
2014-07-01,0.028,2018-01-16 07:54:11
|
||||||
|
2014-12-22,0.105,2018-01-16 07:54:11
|
||||||
|
2016-05-03,0.015,2018-01-16 07:54:11
|
||||||
|
2017-09-01,0.015,2018-01-16 07:54:11
|
||||||
|
2013-06-03,0.02,2018-01-16 07:54:11
|
||||||
|
2013-12-02,0.008,2018-01-16 07:54:11
|
||||||
|
2014-10-01,0.013,2018-01-16 07:54:11
|
||||||
|
2011-10-31,0.003,2018-01-16 07:54:11
|
||||||
|
2017-02-01,0.025,2018-01-16 07:54:11
|
||||||
|
2014-03-03,0.012,2018-01-16 07:54:11
|
||||||
|
2013-09-03,0.026,2018-01-16 07:54:11
|
||||||
|
2018-02-01,0.017,2018-02-26 21:44:31
|
||||||
|
2015-03-02,0.004,2018-02-26 21:44:31
|
||||||
|
2012-09-04,0.036,2018-02-26 21:44:31
|
||||||
|
2012-04-02,0.016,2018-02-26 21:44:31
|
||||||
|
2017-11-01,0.016,2018-02-26 21:44:31
|
||||||
|
2013-08-01,0.025,2018-02-26 21:44:31
|
||||||
|
2018-01-02,0.023,2018-02-26 21:44:31
|
||||||
|
2016-04-01,0.014,2018-02-26 21:44:31
|
||||||
|
2012-03-01,0.057,2018-02-26 21:44:31
|
||||||
|
2015-02-02,0.006,2018-02-26 21:44:31
|
||||||
|
2016-12-01,0.014,2018-02-26 21:44:31
|
||||||
|
2012-07-02,0.038,2018-02-26 21:44:31
|
||||||
|
2016-10-03,0.013,2018-02-26 21:44:31
|
||||||
|
2013-11-01,0.009,2018-02-26 21:44:31
|
||||||
|
2014-01-02,0.007,2018-02-26 21:44:31
|
||||||
|
2016-07-01,0.028,2018-02-26 21:44:31
|
||||||
|
2012-10-01,0.046,2018-02-26 21:44:31
|
||||||
|
2015-06-01,0.01,2018-02-26 21:44:31
|
||||||
|
2015-12-01,0.013,2018-02-26 21:44:31
|
||||||
|
2014-05-01,0.01,2018-02-26 21:44:31
|
||||||
|
2017-04-03,0.018,2018-02-26 21:44:31
|
||||||
|
2012-12-20,0.137,2018-02-26 21:44:31
|
||||||
|
2015-09-01,0.005,2018-02-26 21:44:31
|
||||||
|
2016-03-01,0.013,2018-02-26 21:44:31
|
||||||
|
2011-11-30,0.003,2018-02-26 21:44:31
|
||||||
|
2014-11-03,0.011,2018-02-26 21:44:31
|
||||||
|
2016-11-01,0.013,2018-02-26 21:44:31
|
||||||
|
2012-08-01,0.023,2018-02-26 21:44:31
|
||||||
|
2015-04-01,0.004,2018-02-26 21:44:31
|
||||||
|
2012-05-01,0.006,2018-02-26 21:44:31
|
||||||
|
2016-02-01,0.013,2018-02-26 21:44:31
|
||||||
|
2016-08-01,0.016,2018-02-26 21:44:31
|
||||||
|
2017-12-01,0.017,2018-02-26 21:44:31
|
||||||
|
2015-07-01,0.024,2018-02-26 21:44:31
|
||||||
|
2015-01-02,0.02,2018-02-26 21:44:31
|
||||||
|
2012-01-31,0.004,2018-02-26 21:44:31
|
||||||
|
2012-12-03,0.018,2018-02-26 21:44:31
|
||||||
|
2014-06-02,0.013,2018-02-26 21:44:31
|
||||||
|
2015-10-01,0.014,2018-02-26 21:44:31
|
||||||
|
2013-03-01,0.004,2018-02-26 21:44:31
|
||||||
|
2017-08-01,0.025,2018-02-26 21:44:31
|
||||||
|
2013-05-01,0.009,2018-02-26 21:44:31
|
||||||
|
2013-12-20,0.069,2018-02-26 21:44:31
|
||||||
|
2014-09-02,0.015,2018-02-26 21:44:31
|
||||||
|
2017-03-01,0.013,2018-02-26 21:44:31
|
||||||
|
2015-11-02,0.011,2018-02-26 21:44:31
|
||||||
|
2017-05-01,0.01,2018-02-26 21:44:31
|
||||||
|
2014-04-01,0.009,2018-02-26 21:44:31
|
||||||
|
2016-01-04,0.025,2018-02-26 21:44:31
|
||||||
|
2013-02-01,0.006,2018-02-26 21:44:31
|
||||||
|
2015-08-03,0.009,2018-02-26 21:44:31
|
||||||
|
2017-06-01,0.021,2018-02-26 21:44:31
|
||||||
|
2014-07-01,0.028,2018-02-26 21:44:31
|
||||||
|
2014-12-22,0.105,2018-02-26 21:44:31
|
||||||
|
2016-05-03,0.015,2018-02-26 21:44:31
|
||||||
|
2017-09-01,0.015,2018-02-26 21:44:31
|
||||||
|
2013-06-03,0.02,2018-02-26 21:44:31
|
||||||
|
2013-12-02,0.008,2018-02-26 21:44:31
|
||||||
|
2014-10-01,0.013,2018-02-26 21:44:31
|
||||||
|
2011-10-31,0.003,2018-02-26 21:44:31
|
||||||
|
2017-02-01,0.025,2018-02-26 21:44:31
|
||||||
|
2014-03-03,0.012,2018-02-26 21:44:31
|
||||||
|
2013-09-03,0.026,2018-02-26 21:44:31
|
||||||
|
2018-03-01,0.019,2018-03-09 21:59:16
|
||||||
|
2017-09-01,0.015,2018-03-09 21:59:16
|
||||||
|
2013-06-03,0.02,2018-03-09 21:59:16
|
||||||
|
2013-12-02,0.008,2018-03-09 21:59:16
|
||||||
|
2014-10-01,0.013,2018-03-09 21:59:16
|
||||||
|
2011-10-31,0.003,2018-03-09 21:59:16
|
||||||
|
2017-02-01,0.025,2018-03-09 21:59:16
|
||||||
|
2014-03-03,0.012,2018-03-09 21:59:16
|
||||||
|
2013-09-03,0.026,2018-03-09 21:59:16
|
||||||
|
2018-04-02,0.021,2018-04-13 15:05:34
|
||||||
|
2015-05-01,0.005,2018-04-13 15:05:34
|
||||||
|
2018-02-01,0.017,2018-04-13 15:05:34
|
||||||
|
2015-03-02,0.004,2018-04-13 15:05:34
|
||||||
|
2012-09-04,0.036,2018-04-13 15:05:34
|
||||||
|
2012-04-02,0.016,2018-04-13 15:05:34
|
||||||
|
2017-11-01,0.016,2018-04-13 15:05:34
|
||||||
|
2013-08-01,0.025,2018-04-13 15:05:34
|
||||||
|
2018-01-02,0.023,2018-04-13 15:05:34
|
||||||
|
2016-04-01,0.014,2018-04-13 15:05:34
|
||||||
|
2012-03-01,0.057,2018-04-13 15:05:34
|
||||||
|
2015-02-02,0.006,2018-04-13 15:05:34
|
||||||
|
2016-12-01,0.014,2018-04-13 15:05:34
|
||||||
|
2012-07-02,0.038,2018-04-13 15:05:34
|
||||||
|
2016-10-03,0.013,2018-04-13 15:05:34
|
||||||
|
2013-11-01,0.009,2018-04-13 15:05:34
|
||||||
|
2014-01-02,0.007,2018-04-13 15:05:34
|
||||||
|
2016-07-01,0.028,2018-04-13 15:05:34
|
||||||
|
2012-10-01,0.046,2018-04-13 15:05:34
|
||||||
|
2015-06-01,0.01,2018-04-13 15:05:34
|
||||||
|
2015-12-01,0.013,2018-04-13 15:05:34
|
||||||
|
2014-05-01,0.01,2018-04-13 15:05:34
|
||||||
|
2017-04-03,0.018,2018-04-13 15:05:34
|
||||||
|
2012-12-20,0.137,2018-04-13 15:05:34
|
||||||
|
2015-09-01,0.005,2018-04-13 15:05:34
|
||||||
|
2016-03-01,0.013,2018-04-13 15:05:34
|
||||||
|
2011-11-30,0.003,2018-04-13 15:05:34
|
||||||
|
2014-11-03,0.011,2018-04-13 15:05:34
|
||||||
|
2016-11-01,0.013,2018-04-13 15:05:34
|
||||||
|
2012-08-01,0.023,2018-04-13 15:05:34
|
||||||
|
2015-04-01,0.004,2018-04-13 15:05:34
|
||||||
|
2012-05-01,0.006,2018-04-13 15:05:34
|
||||||
|
2016-02-01,0.013,2018-04-13 15:05:34
|
||||||
|
2016-08-01,0.016,2018-04-13 15:05:34
|
||||||
|
2017-12-01,0.017,2018-04-13 15:05:34
|
||||||
|
2015-07-01,0.024,2018-04-13 15:05:34
|
||||||
|
2015-01-02,0.02,2018-04-13 15:05:34
|
||||||
|
2012-01-31,0.004,2018-04-13 15:05:34
|
||||||
|
2012-12-03,0.018,2018-04-13 15:05:34
|
||||||
|
2014-06-02,0.013,2018-04-13 15:05:34
|
||||||
|
2015-10-01,0.014,2018-04-13 15:05:34
|
||||||
|
2013-03-01,0.004,2018-04-13 15:05:34
|
||||||
|
2017-08-01,0.025,2018-04-13 15:05:34
|
||||||
|
2013-05-01,0.009,2018-04-13 15:05:34
|
||||||
|
2013-12-20,0.069,2018-04-13 15:05:34
|
||||||
|
2014-09-02,0.015,2018-04-13 15:05:34
|
||||||
|
2017-03-01,0.013,2018-04-13 15:05:34
|
||||||
|
2015-11-02,0.011,2018-04-13 15:05:34
|
||||||
|
2017-05-01,0.01,2018-04-13 15:05:34
|
||||||
|
2014-04-01,0.009,2018-04-13 15:05:34
|
||||||
|
2016-01-04,0.025,2018-04-13 15:05:34
|
||||||
|
2013-02-01,0.006,2018-04-13 15:05:34
|
||||||
|
2015-08-03,0.009,2018-04-13 15:05:34
|
||||||
|
2017-06-01,0.021,2018-04-13 15:05:34
|
||||||
|
2014-07-01,0.028,2018-04-13 15:05:34
|
||||||
|
2014-12-22,0.105,2018-04-13 15:05:34
|
||||||
|
2016-05-03,0.015,2018-04-13 15:05:34
|
||||||
|
2018-03-01,0.019,2018-04-13 15:05:34
|
||||||
|
2017-09-01,0.015,2018-04-13 15:05:34
|
||||||
|
2013-06-03,0.02,2018-04-13 15:05:34
|
||||||
|
2013-12-02,0.008,2018-04-13 15:05:34
|
||||||
|
2014-10-01,0.013,2018-04-13 15:05:34
|
||||||
|
2011-10-31,0.003,2018-04-13 15:05:34
|
||||||
|
2017-02-01,0.025,2018-04-13 15:05:34
|
||||||
|
2014-03-03,0.012,2018-04-13 15:05:34
|
||||||
|
2013-09-03,0.026,2018-04-13 15:05:34
|
||||||
|
2018-05-01,0.023,2018-12-20 11:23:51
|
||||||
|
2012-10-01,0.046,2018-12-20 11:23:51
|
||||||
|
2015-06-01,0.01,2018-12-20 11:23:51
|
||||||
|
2015-12-01,0.013,2018-12-20 11:23:51
|
||||||
|
2018-08-01,0.033,2018-12-20 11:23:51
|
||||||
|
2014-05-01,0.01,2018-12-20 11:23:51
|
||||||
|
2017-04-03,0.018,2018-12-20 11:23:51
|
||||||
|
2012-12-20,0.137,2018-12-20 11:23:51
|
||||||
|
2015-09-01,0.005,2018-12-20 11:23:51
|
||||||
|
2016-03-01,0.013,2018-12-20 11:23:51
|
||||||
|
2011-11-30,0.003,2018-12-20 11:23:51
|
||||||
|
2014-11-03,0.011,2018-12-20 11:23:51
|
||||||
|
2016-11-01,0.013,2018-12-20 11:23:51
|
||||||
|
2012-08-01,0.023,2018-12-20 11:23:51
|
||||||
|
2015-04-01,0.004,2018-12-20 11:23:51
|
||||||
|
2012-05-01,0.006,2018-12-20 11:23:51
|
||||||
|
2016-02-01,0.013,2018-12-20 11:23:51
|
||||||
|
2016-08-01,0.016,2018-12-20 11:23:51
|
||||||
|
2017-12-01,0.017,2018-12-20 11:23:51
|
||||||
|
2018-06-01,0.021,2018-12-20 11:23:51
|
||||||
|
2015-07-01,0.024,2018-12-20 11:23:51
|
||||||
|
2015-01-02,0.02,2018-12-20 11:23:51
|
||||||
|
2012-01-31,0.004,2018-12-20 11:23:51
|
||||||
|
2012-12-03,0.018,2018-12-20 11:23:51
|
||||||
|
2014-06-02,0.013,2018-12-20 11:23:51
|
||||||
|
2015-10-01,0.014,2018-12-20 11:23:51
|
||||||
|
2018-09-04,0.023,2018-12-20 11:23:51
|
||||||
|
2013-03-01,0.004,2018-12-20 11:23:51
|
||||||
|
2017-08-01,0.025,2018-12-20 11:23:51
|
||||||
|
2013-05-01,0.009,2018-12-20 11:23:51
|
||||||
|
2013-12-20,0.069,2018-12-20 11:23:51
|
||||||
|
2014-09-02,0.015,2018-12-20 11:23:51
|
||||||
|
2017-03-01,0.013,2018-12-20 11:23:51
|
||||||
|
2015-11-02,0.011,2018-12-20 11:23:51
|
||||||
|
2017-05-01,0.01,2018-12-20 11:23:51
|
||||||
|
2014-04-01,0.009,2018-12-20 11:23:51
|
||||||
|
2016-01-04,0.025,2018-12-20 11:23:51
|
||||||
|
2018-07-02,0.022,2018-12-20 11:23:51
|
||||||
|
2013-02-01,0.006,2018-12-20 11:23:51
|
||||||
|
2015-08-03,0.009,2018-12-20 11:23:51
|
||||||
|
2017-06-01,0.021,2018-12-20 11:23:51
|
||||||
|
2014-07-01,0.028,2018-12-20 11:23:51
|
||||||
|
2018-10-01,0.008,2018-12-20 11:23:51
|
||||||
|
2014-12-22,0.105,2018-12-20 11:23:51
|
||||||
|
2016-05-03,0.015,2018-12-20 11:23:51
|
||||||
|
2018-03-01,0.019,2018-12-20 11:23:51
|
||||||
|
2017-09-01,0.015,2018-12-20 11:23:51
|
||||||
|
2013-06-03,0.02,2018-12-20 11:23:51
|
||||||
|
2013-12-02,0.008,2018-12-20 11:23:51
|
||||||
|
2014-10-01,0.013,2018-12-20 11:23:51
|
||||||
|
2011-10-31,0.003,2018-12-20 11:23:51
|
||||||
|
2017-02-01,0.025,2018-12-20 11:23:51
|
||||||
|
2014-03-03,0.012,2018-12-20 11:23:51
|
||||||
|
2013-09-03,0.026,2018-12-20 11:23:51
|
||||||
|
16800
overrides/frozen/afxpx-history.csv
Normal file
16800
overrides/frozen/afxpx-history.csv
Normal file
File diff suppressed because it is too large
Load Diff
7
overrides/frozen/afxpx.json
Normal file
7
overrides/frozen/afxpx.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"symbol": "afxpx",
|
||||||
|
"longName": "?",
|
||||||
|
"freeze_date": "2018-12-11",
|
||||||
|
"created": "2026-08-31",
|
||||||
|
"reason": "yahoo-empty"
|
||||||
|
}
|
||||||
7
overrides/frozen/agazx-capitalGain.csv
Normal file
7
overrides/frozen/agazx-capitalGain.csv
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
Date,Capital Gains
|
||||||
|
2015-12-03,0.093000
|
||||||
|
2017-12-05,0.759000
|
||||||
|
2018-12-07,0.334000
|
||||||
|
2021-12-09,0.367000
|
||||||
|
2024-12-12,0.260000
|
||||||
|
2025-02-21,1.364000
|
||||||
|
9
overrides/frozen/agazx-dividend.csv
Normal file
9
overrides/frozen/agazx-dividend.csv
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
Date,Dividends
|
||||||
|
2023-12-27,0.342230
|
||||||
|
2024-12-12,0.260230
|
||||||
|
2024-12-27,0.210040
|
||||||
|
2025-02-21,1.363530
|
||||||
|
2025-03-25,0.134190
|
||||||
|
2019-12-09,0.032500
|
||||||
|
2021-12-09,0.367200
|
||||||
|
2022-12-28,0.098270
|
||||||
|
1572
overrides/frozen/agazx-history.csv
Normal file
1572
overrides/frozen/agazx-history.csv
Normal file
File diff suppressed because it is too large
Load Diff
7
overrides/frozen/agazx.json
Normal file
7
overrides/frozen/agazx.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"symbol": "agazx",
|
||||||
|
"longName": "Allspring Funds Trust - Allspring Global Long/Short Equity Fund",
|
||||||
|
"freeze_date": "2025-04-07",
|
||||||
|
"created": "2026-08-31",
|
||||||
|
"reason": "yahoo-empty"
|
||||||
|
}
|
||||||
13
overrides/frozen/akrex-capitalGain.csv
Normal file
13
overrides/frozen/akrex-capitalGain.csv
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
Date,Capital Gains
|
||||||
|
2021-12-10,2.340000
|
||||||
|
2023-12-08,2.044000
|
||||||
|
2024-12-06,3.273000
|
||||||
|
2012-12-14,0.252000
|
||||||
|
2014-12-12,0.467000
|
||||||
|
2016-12-16,0.046000
|
||||||
|
2017-12-15,0.200000
|
||||||
|
2019-12-13,1.331000
|
||||||
|
2025-08-25,3.020000
|
||||||
|
2013-12-13,0.404000
|
||||||
|
2018-12-14,0.188000
|
||||||
|
2022-12-09,3.120000
|
||||||
|
7
overrides/frozen/akrex-dividend.csv
Normal file
7
overrides/frozen/akrex-dividend.csv
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
Date,Dividends
|
||||||
|
2021-12-10,2.340140
|
||||||
|
2022-12-09,3.120430
|
||||||
|
2023-12-08,2.044210
|
||||||
|
2024-12-06,3.272590
|
||||||
|
2025-08-25,3.020290
|
||||||
|
2019-12-13,1.330690
|
||||||
|
1702
overrides/frozen/akrex-history.csv
Normal file
1702
overrides/frozen/akrex-history.csv
Normal file
File diff suppressed because it is too large
Load Diff
7
overrides/frozen/akrex.json
Normal file
7
overrides/frozen/akrex.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"symbol": "akrex",
|
||||||
|
"longName": "Akre Focus Retail",
|
||||||
|
"freeze_date": "2025-10-09",
|
||||||
|
"created": "2026-08-31",
|
||||||
|
"reason": "yahoo-empty"
|
||||||
|
}
|
||||||
9
overrides/frozen/alasx-dividend.csv
Normal file
9
overrides/frozen/alasx-dividend.csv
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
Date,Dividends,ctime
|
||||||
|
2014-12-18,0.078,2017-08-22
|
||||||
|
2015-12-17,0.042,2017-08-22
|
||||||
|
2016-12-15,0.117,2017-08-22
|
||||||
|
2015-03-10,0.007,2017-08-22
|
||||||
|
2014-09-09,0.042,2017-08-22
|
||||||
|
2017-12-14,0.08,2017-12-27 07:42:40
|
||||||
|
2015-03-10,0.007,2017-12-27 07:42:40
|
||||||
|
2014-09-09,0.042,2017-12-27 07:42:40
|
||||||
|
8399
overrides/frozen/alasx-history.csv
Normal file
8399
overrides/frozen/alasx-history.csv
Normal file
File diff suppressed because it is too large
Load Diff
7
overrides/frozen/alasx.json
Normal file
7
overrides/frozen/alasx.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"symbol": "alasx",
|
||||||
|
"longName": "?",
|
||||||
|
"freeze_date": "2018-04-27",
|
||||||
|
"created": "2026-08-31",
|
||||||
|
"reason": "yahoo-empty"
|
||||||
|
}
|
||||||
16
overrides/frozen/amfzx-dividend.csv
Normal file
16
overrides/frozen/amfzx-dividend.csv
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
Date,Dividends,ctime
|
||||||
|
2012-12-18,0.011,2017-08-22
|
||||||
|
2013-12-17,0.403,2017-08-22
|
||||||
|
2014-12-17,0.292,2017-08-22
|
||||||
|
2019-02-07,4.44,2019-12-19 07:25:20
|
||||||
|
2019-03-07,4.43,2019-04-16 10:50:03
|
||||||
|
2019-02-07,4.44,2019-04-16 10:50:03
|
||||||
|
2019-04-09,4.45,2019-04-16 10:50:03
|
||||||
|
2019-12-09,0.158,2019-12-19 07:25:20
|
||||||
|
2012-12-18,0.0,2021-03-01 22:16:32
|
||||||
|
2012-12-18,0.011,2019-12-19 07:25:20
|
||||||
|
2013-12-17,0.0,2021-03-01 22:16:32
|
||||||
|
2013-12-17,0.403,2019-12-19 07:25:20
|
||||||
|
2014-12-17,0.0,2021-03-01 22:16:32
|
||||||
|
2014-12-17,0.292,2019-12-19 07:25:20
|
||||||
|
2019-03-07,4.43,2019-12-19 07:25:20
|
||||||
|
573
overrides/frozen/amfzx-history.csv
Normal file
573
overrides/frozen/amfzx-history.csv
Normal file
|
|
@ -0,0 +1,573 @@
|
||||||
|
Date,Open,High,Low,Close,Adj Close,Volume
|
||||||
|
2019-01-02,11.430000,11.430000,11.430000,11.430000,11.430000,0
|
||||||
|
2019-01-03,11.430000,11.430000,11.430000,11.430000,11.430000,0
|
||||||
|
2019-01-04,11.530000,11.530000,11.530000,11.530000,11.530000,0
|
||||||
|
2019-01-07,11.470000,11.470000,11.470000,11.470000,11.470000,0
|
||||||
|
2019-01-08,11.360000,11.360000,11.360000,11.360000,11.360000,0
|
||||||
|
2019-01-09,11.300000,11.300000,11.300000,11.300000,11.300000,0
|
||||||
|
2019-01-10,11.250000,11.250000,11.250000,11.250000,11.250000,0
|
||||||
|
2019-01-11,11.250000,11.250000,11.250000,11.250000,11.250000,0
|
||||||
|
2019-01-14,11.300000,11.300000,11.300000,11.300000,11.300000,0
|
||||||
|
2019-01-15,11.280000,11.280000,11.280000,11.280000,11.280000,0
|
||||||
|
2019-01-16,11.250000,11.250000,11.250000,11.250000,11.250000,0
|
||||||
|
2019-01-17,11.170000,11.170000,11.170000,11.170000,11.170000,0
|
||||||
|
2019-01-18,11.040000,11.040000,11.040000,11.040000,11.040000,0
|
||||||
|
2019-01-22,11.220000,11.220000,11.220000,11.220000,11.220000,0
|
||||||
|
2019-01-23,11.220000,11.220000,11.220000,11.220000,11.220000,0
|
||||||
|
2019-01-24,11.230000,11.230000,11.230000,11.230000,11.230000,0
|
||||||
|
2019-01-25,11.210000,11.210000,11.210000,11.210000,11.210000,0
|
||||||
|
2019-01-28,11.290000,11.290000,11.290000,11.290000,11.290000,0
|
||||||
|
2019-01-29,11.290000,11.290000,11.290000,11.290000,11.290000,0
|
||||||
|
2019-01-30,11.260000,11.260000,11.260000,11.260000,11.260000,0
|
||||||
|
2019-01-31,11.230000,11.230000,11.230000,11.230000,11.230000,0
|
||||||
|
2019-02-01,11.250000,11.250000,11.250000,11.250000,11.250000,0
|
||||||
|
2019-02-04,11.240000,11.240000,11.240000,11.240000,11.240000,0
|
||||||
|
2019-02-05,11.240000,11.240000,11.240000,11.240000,11.240000,0
|
||||||
|
2019-02-06,11.250000,11.250000,11.250000,11.250000,11.250000,0
|
||||||
|
2019-02-07,11.240000,11.240000,11.240000,11.240000,11.240000,0
|
||||||
|
2019-02-08,11.240000,11.240000,11.240000,11.240000,11.240000,0
|
||||||
|
2019-02-11,11.240000,11.240000,11.240000,11.240000,11.240000,0
|
||||||
|
2019-02-12,11.260000,11.260000,11.260000,11.260000,11.260000,0
|
||||||
|
2019-02-13,11.260000,11.260000,11.260000,11.260000,11.260000,0
|
||||||
|
2019-02-14,11.260000,11.260000,11.260000,11.260000,11.260000,0
|
||||||
|
2019-02-15,11.260000,11.260000,11.260000,11.260000,11.260000,0
|
||||||
|
2019-02-19,11.260000,11.260000,11.260000,11.260000,11.260000,0
|
||||||
|
2019-02-20,11.280000,11.280000,11.280000,11.280000,11.280000,0
|
||||||
|
2019-02-21,11.280000,11.280000,11.280000,11.280000,11.280000,0
|
||||||
|
2019-02-22,11.300000,11.300000,11.300000,11.300000,11.300000,0
|
||||||
|
2019-02-25,11.280000,11.280000,11.280000,11.280000,11.280000,0
|
||||||
|
2019-02-26,11.280000,11.280000,11.280000,11.280000,11.280000,0
|
||||||
|
2019-02-27,11.280000,11.280000,11.280000,11.280000,11.280000,0
|
||||||
|
2019-02-28,11.280000,11.280000,11.280000,11.280000,11.280000,0
|
||||||
|
2019-03-01,11.300000,11.300000,11.300000,11.300000,11.300000,0
|
||||||
|
2019-03-04,11.280000,11.280000,11.280000,11.280000,11.280000,0
|
||||||
|
2019-03-05,11.270000,11.270000,11.270000,11.270000,11.270000,0
|
||||||
|
2019-03-06,11.240000,11.240000,11.240000,11.240000,11.240000,0
|
||||||
|
2019-03-07,11.200000,11.200000,11.200000,11.200000,11.200000,0
|
||||||
|
2019-03-08,11.200000,11.200000,11.200000,11.200000,11.200000,0
|
||||||
|
2019-03-11,11.400000,11.400000,11.400000,11.400000,11.400000,0
|
||||||
|
2019-03-12,11.420000,11.420000,11.420000,11.420000,11.420000,0
|
||||||
|
2019-03-13,11.430000,11.430000,11.430000,11.430000,11.430000,0
|
||||||
|
2019-03-14,11.430000,11.430000,11.430000,11.430000,11.430000,0
|
||||||
|
2019-03-15,11.450000,11.450000,11.450000,11.450000,11.450000,0
|
||||||
|
2019-03-18,11.440000,11.440000,11.440000,11.440000,11.440000,0
|
||||||
|
2019-03-19,11.440000,11.440000,11.440000,11.440000,11.440000,0
|
||||||
|
2019-03-20,11.430000,11.430000,11.430000,11.430000,11.430000,0
|
||||||
|
2019-03-21,11.440000,11.440000,11.440000,11.440000,11.440000,0
|
||||||
|
2019-03-22,11.390000,11.390000,11.390000,11.390000,11.390000,0
|
||||||
|
2019-03-25,11.410000,11.410000,11.410000,11.410000,11.410000,0
|
||||||
|
2019-03-26,11.450000,11.450000,11.450000,11.450000,11.450000,0
|
||||||
|
2019-03-27,11.430000,11.430000,11.430000,11.430000,11.430000,0
|
||||||
|
2019-03-28,11.470000,11.470000,11.470000,11.470000,11.470000,0
|
||||||
|
2019-03-29,11.490000,11.490000,11.490000,11.490000,11.490000,0
|
||||||
|
2019-04-01,11.500000,11.500000,11.500000,11.500000,11.500000,0
|
||||||
|
2019-04-02,11.500000,11.500000,11.500000,11.500000,11.500000,0
|
||||||
|
2019-04-03,11.500000,11.500000,11.500000,11.500000,11.500000,0
|
||||||
|
2019-04-04,11.510000,11.510000,11.510000,11.510000,11.510000,0
|
||||||
|
2019-04-05,11.520000,11.520000,11.520000,11.520000,11.520000,0
|
||||||
|
2019-04-08,11.520000,11.520000,11.520000,11.520000,11.520000,0
|
||||||
|
2019-04-09,11.500000,11.500000,11.500000,11.500000,11.500000,0
|
||||||
|
2019-04-10,11.530000,11.530000,11.530000,11.530000,11.530000,0
|
||||||
|
2019-04-11,11.540000,11.540000,11.540000,11.540000,11.540000,0
|
||||||
|
2019-04-12,11.580000,11.580000,11.580000,11.580000,11.580000,0
|
||||||
|
2019-04-15,11.580000,11.580000,11.580000,11.580000,11.580000,0
|
||||||
|
2019-04-16,11.580000,11.580000,11.580000,11.580000,11.580000,0
|
||||||
|
2019-04-17,11.580000,11.580000,11.580000,11.580000,11.580000,0
|
||||||
|
2019-04-18,11.580000,11.580000,11.580000,11.580000,11.580000,0
|
||||||
|
2019-04-22,11.590000,11.590000,11.590000,11.590000,11.590000,0
|
||||||
|
2019-04-23,11.640000,11.640000,11.640000,11.640000,11.640000,0
|
||||||
|
2019-04-24,11.630000,11.630000,11.630000,11.630000,11.630000,0
|
||||||
|
2019-04-25,11.620000,11.620000,11.620000,11.620000,11.620000,0
|
||||||
|
2019-04-26,11.640000,11.640000,11.640000,11.640000,11.640000,0
|
||||||
|
2019-04-29,11.640000,11.640000,11.640000,11.640000,11.640000,0
|
||||||
|
2019-04-30,11.640000,11.640000,11.640000,11.640000,11.640000,0
|
||||||
|
2019-05-01,11.610000,11.610000,11.610000,11.610000,11.610000,0
|
||||||
|
2019-05-02,11.600000,11.600000,11.600000,11.600000,11.600000,0
|
||||||
|
2019-05-03,11.620000,11.620000,11.620000,11.620000,11.620000,0
|
||||||
|
2019-05-06,11.570000,11.570000,11.570000,11.570000,11.570000,0
|
||||||
|
2019-05-07,11.570000,11.570000,11.570000,11.570000,11.570000,0
|
||||||
|
2019-05-08,11.560000,11.560000,11.560000,11.560000,11.560000,0
|
||||||
|
2019-05-09,11.510000,11.510000,11.510000,11.510000,11.510000,0
|
||||||
|
2019-05-10,11.540000,11.540000,11.540000,11.540000,11.540000,0
|
||||||
|
2019-05-13,11.180000,11.180000,11.180000,11.180000,11.180000,0
|
||||||
|
2019-05-14,11.330000,11.330000,11.330000,11.330000,11.330000,0
|
||||||
|
2019-05-15,11.330000,11.330000,11.330000,11.330000,11.330000,0
|
||||||
|
2019-05-16,11.330000,11.330000,11.330000,11.330000,11.330000,0
|
||||||
|
2019-05-17,11.330000,11.330000,11.330000,11.330000,11.330000,0
|
||||||
|
2019-05-20,11.320000,11.320000,11.320000,11.320000,11.320000,0
|
||||||
|
2019-05-21,11.380000,11.380000,11.380000,11.380000,11.380000,0
|
||||||
|
2019-05-22,11.360000,11.360000,11.360000,11.360000,11.360000,0
|
||||||
|
2019-05-23,11.290000,11.290000,11.290000,11.290000,11.290000,0
|
||||||
|
2019-05-24,11.350000,11.350000,11.350000,11.350000,11.350000,0
|
||||||
|
2019-05-28,11.270000,11.270000,11.270000,11.270000,11.270000,0
|
||||||
|
2019-05-29,11.160000,11.160000,11.160000,11.160000,11.160000,0
|
||||||
|
2019-05-30,11.190000,11.190000,11.190000,11.190000,11.190000,0
|
||||||
|
2019-05-31,11.040000,11.040000,11.040000,11.040000,11.040000,0
|
||||||
|
2019-06-03,10.990000,10.990000,10.990000,10.990000,10.990000,0
|
||||||
|
2019-06-04,11.240000,11.240000,11.240000,11.240000,11.240000,0
|
||||||
|
2019-06-05,11.230000,11.230000,11.230000,11.230000,11.230000,0
|
||||||
|
2019-06-06,11.240000,11.240000,11.240000,11.240000,11.240000,0
|
||||||
|
2019-06-07,11.230000,11.230000,11.230000,11.230000,11.230000,0
|
||||||
|
2019-06-10,11.240000,11.240000,11.240000,11.240000,11.240000,0
|
||||||
|
2019-06-11,11.230000,11.230000,11.230000,11.230000,11.230000,0
|
||||||
|
2019-06-12,11.240000,11.240000,11.240000,11.240000,11.240000,0
|
||||||
|
2019-06-13,11.240000,11.240000,11.240000,11.240000,11.240000,0
|
||||||
|
2019-06-14,11.240000,11.240000,11.240000,11.240000,11.240000,0
|
||||||
|
2019-06-17,11.240000,11.240000,11.240000,11.240000,11.240000,0
|
||||||
|
2019-06-18,11.240000,11.240000,11.240000,11.240000,11.240000,0
|
||||||
|
2019-06-19,11.250000,11.250000,11.250000,11.250000,11.250000,0
|
||||||
|
2019-06-20,11.250000,11.250000,11.250000,11.250000,11.250000,0
|
||||||
|
2019-06-21,11.240000,11.240000,11.240000,11.240000,11.240000,0
|
||||||
|
2019-06-24,11.240000,11.240000,11.240000,11.240000,11.240000,0
|
||||||
|
2019-06-25,11.220000,11.220000,11.220000,11.220000,11.220000,0
|
||||||
|
2019-06-26,11.220000,11.220000,11.220000,11.220000,11.220000,0
|
||||||
|
2019-06-27,11.250000,11.250000,11.250000,11.250000,11.250000,0
|
||||||
|
2019-06-28,11.250000,11.250000,11.250000,11.250000,11.250000,0
|
||||||
|
2019-07-01,11.250000,11.250000,11.250000,11.250000,11.250000,0
|
||||||
|
2019-07-02,11.270000,11.270000,11.270000,11.270000,11.270000,0
|
||||||
|
2019-07-03,11.280000,11.280000,11.280000,11.280000,11.280000,0
|
||||||
|
2019-07-05,11.270000,11.270000,11.270000,11.270000,11.270000,0
|
||||||
|
2019-07-08,11.250000,11.250000,11.250000,11.250000,11.250000,0
|
||||||
|
2019-07-09,11.250000,11.250000,11.250000,11.250000,11.250000,0
|
||||||
|
2019-07-10,11.290000,11.290000,11.290000,11.290000,11.290000,0
|
||||||
|
2019-07-11,11.290000,11.290000,11.290000,11.290000,11.290000,0
|
||||||
|
2019-07-12,11.300000,11.300000,11.300000,11.300000,11.300000,0
|
||||||
|
2019-07-15,11.300000,11.300000,11.300000,11.300000,11.300000,0
|
||||||
|
2019-07-16,11.300000,11.300000,11.300000,11.300000,11.300000,0
|
||||||
|
2019-07-17,11.280000,11.280000,11.280000,11.280000,11.280000,0
|
||||||
|
2019-07-18,11.310000,11.310000,11.310000,11.310000,11.310000,0
|
||||||
|
2019-07-19,11.240000,11.240000,11.240000,11.240000,11.240000,0
|
||||||
|
2019-07-22,11.290000,11.290000,11.290000,11.290000,11.290000,0
|
||||||
|
2019-07-23,11.350000,11.350000,11.350000,11.350000,11.350000,0
|
||||||
|
2019-07-24,11.360000,11.360000,11.360000,11.360000,11.360000,0
|
||||||
|
2019-07-25,11.360000,11.360000,11.360000,11.360000,11.360000,0
|
||||||
|
2019-07-26,11.420000,11.420000,11.420000,11.420000,11.420000,0
|
||||||
|
2019-07-29,11.430000,11.430000,11.430000,11.430000,11.430000,0
|
||||||
|
2019-07-30,11.390000,11.390000,11.390000,11.390000,11.390000,0
|
||||||
|
2019-07-31,11.350000,11.350000,11.350000,11.350000,11.350000,0
|
||||||
|
2019-08-01,11.280000,11.280000,11.280000,11.280000,11.280000,0
|
||||||
|
2019-08-02,11.210000,11.210000,11.210000,11.210000,11.210000,0
|
||||||
|
2019-08-05,10.820000,10.820000,10.820000,10.820000,10.820000,0
|
||||||
|
2019-08-06,10.980000,10.980000,10.980000,10.980000,10.980000,0
|
||||||
|
2019-08-07,11.010000,11.010000,11.010000,11.010000,11.010000,0
|
||||||
|
2019-08-08,11.170000,11.170000,11.170000,11.170000,11.170000,0
|
||||||
|
2019-08-09,11.180000,11.180000,11.180000,11.180000,11.180000,0
|
||||||
|
2019-08-12,11.150000,11.150000,11.150000,11.150000,11.150000,0
|
||||||
|
2019-08-13,11.300000,11.300000,11.300000,11.300000,11.300000,0
|
||||||
|
2019-08-14,11.240000,11.240000,11.240000,11.240000,11.240000,0
|
||||||
|
2019-08-15,11.240000,11.240000,11.240000,11.240000,11.240000,0
|
||||||
|
2019-08-16,11.420000,11.420000,11.420000,11.420000,11.420000,0
|
||||||
|
2019-08-19,11.410000,11.410000,11.410000,11.410000,11.410000,0
|
||||||
|
2019-08-20,11.440000,11.440000,11.440000,11.440000,11.440000,0
|
||||||
|
2019-08-21,11.400000,11.400000,11.400000,11.400000,11.400000,0
|
||||||
|
2019-08-22,11.390000,11.390000,11.390000,11.390000,11.390000,0
|
||||||
|
2019-08-23,11.370000,11.370000,11.370000,11.370000,11.370000,0
|
||||||
|
2019-08-26,11.500000,11.500000,11.500000,11.500000,11.500000,0
|
||||||
|
2019-08-27,11.400000,11.400000,11.400000,11.400000,11.400000,0
|
||||||
|
2019-08-28,11.500000,11.500000,11.500000,11.500000,11.500000,0
|
||||||
|
2019-08-29,11.660000,11.660000,11.660000,11.660000,11.660000,0
|
||||||
|
2019-08-30,11.660000,11.660000,11.660000,11.660000,11.660000,0
|
||||||
|
2019-09-03,11.660000,11.660000,11.660000,11.660000,11.660000,0
|
||||||
|
2019-09-04,11.670000,11.670000,11.670000,11.670000,11.670000,0
|
||||||
|
2019-09-05,11.690000,11.690000,11.690000,11.690000,11.690000,0
|
||||||
|
2019-09-06,11.730000,11.730000,11.730000,11.730000,11.730000,0
|
||||||
|
2019-09-09,11.730000,11.730000,11.730000,11.730000,11.730000,0
|
||||||
|
2019-09-10,11.730000,11.730000,11.730000,11.730000,11.730000,0
|
||||||
|
2019-09-11,11.670000,11.670000,11.670000,11.670000,11.670000,0
|
||||||
|
2019-09-12,11.670000,11.670000,11.670000,11.670000,11.670000,0
|
||||||
|
2019-09-13,11.680000,11.680000,11.680000,11.680000,11.680000,0
|
||||||
|
2019-09-16,11.650000,11.650000,11.650000,11.650000,11.650000,0
|
||||||
|
2019-09-17,11.670000,11.670000,11.670000,11.670000,11.670000,0
|
||||||
|
2019-09-18,11.700000,11.700000,11.700000,11.700000,11.700000,0
|
||||||
|
2019-09-19,11.690000,11.690000,11.690000,11.690000,11.690000,0
|
||||||
|
2019-09-20,11.640000,11.640000,11.640000,11.640000,11.640000,0
|
||||||
|
2019-09-23,11.670000,11.670000,11.670000,11.670000,11.670000,0
|
||||||
|
2019-09-24,11.550000,11.550000,11.550000,11.550000,11.550000,0
|
||||||
|
2019-09-25,11.640000,11.640000,11.640000,11.640000,11.640000,0
|
||||||
|
2019-09-26,11.630000,11.630000,11.630000,11.630000,11.630000,0
|
||||||
|
2019-09-27,11.610000,11.610000,11.610000,11.610000,11.610000,0
|
||||||
|
2019-09-30,11.680000,11.680000,11.680000,11.680000,11.680000,0
|
||||||
|
2019-10-01,11.660000,11.660000,11.660000,11.660000,11.660000,0
|
||||||
|
2019-10-02,11.660000,11.660000,11.660000,11.660000,11.660000,0
|
||||||
|
2019-10-03,11.750000,11.750000,11.750000,11.750000,11.750000,0
|
||||||
|
2019-10-04,11.790000,11.790000,11.790000,11.790000,11.790000,0
|
||||||
|
2019-10-07,11.790000,11.790000,11.790000,11.790000,11.790000,0
|
||||||
|
2019-10-08,11.790000,11.790000,11.790000,11.790000,11.790000,0
|
||||||
|
2019-10-09,11.870000,11.870000,11.870000,11.870000,11.870000,0
|
||||||
|
2019-10-10,11.890000,11.890000,11.890000,11.890000,11.890000,0
|
||||||
|
2019-10-11,11.880000,11.880000,11.880000,11.880000,11.880000,0
|
||||||
|
2019-10-14,11.900000,11.900000,11.900000,11.900000,11.900000,0
|
||||||
|
2019-10-15,11.910000,11.910000,11.910000,11.910000,11.910000,0
|
||||||
|
2019-10-16,11.920000,11.920000,11.920000,11.920000,11.920000,0
|
||||||
|
2019-10-17,11.920000,11.920000,11.920000,11.920000,11.920000,0
|
||||||
|
2019-10-18,11.920000,11.920000,11.920000,11.920000,11.920000,0
|
||||||
|
2019-10-21,11.970000,11.970000,11.970000,11.970000,11.970000,0
|
||||||
|
2019-10-22,11.950000,11.950000,11.950000,11.950000,11.950000,0
|
||||||
|
2019-10-23,11.970000,11.970000,11.970000,11.970000,11.970000,0
|
||||||
|
2019-10-24,11.980000,11.980000,11.980000,11.980000,11.980000,0
|
||||||
|
2019-10-25,12.000000,12.000000,12.000000,12.000000,12.000000,0
|
||||||
|
2019-10-28,11.990000,11.990000,11.990000,11.990000,11.990000,0
|
||||||
|
2019-10-29,12.000000,12.000000,12.000000,12.000000,12.000000,0
|
||||||
|
2019-10-30,12.020000,12.020000,12.020000,12.020000,12.020000,0
|
||||||
|
2019-10-31,12.030000,12.030000,12.030000,12.030000,12.030000,0
|
||||||
|
2019-11-01,12.130000,12.130000,12.130000,12.130000,12.130000,0
|
||||||
|
2019-11-04,12.130000,12.130000,12.130000,12.130000,12.130000,0
|
||||||
|
2019-11-05,12.120000,12.120000,12.120000,12.120000,12.120000,0
|
||||||
|
2019-11-06,12.130000,12.130000,12.130000,12.130000,12.130000,0
|
||||||
|
2019-11-07,12.130000,12.130000,12.130000,12.130000,12.130000,0
|
||||||
|
2019-11-08,12.160000,12.160000,12.160000,12.160000,12.160000,0
|
||||||
|
2019-11-11,12.160000,12.160000,12.160000,12.160000,12.160000,0
|
||||||
|
2019-11-12,12.170000,12.170000,12.170000,12.170000,12.170000,0
|
||||||
|
2019-11-13,12.160000,12.160000,12.160000,12.160000,12.160000,0
|
||||||
|
2019-11-14,12.170000,12.170000,12.170000,12.170000,12.170000,0
|
||||||
|
2019-11-15,12.200000,12.200000,12.200000,12.200000,12.200000,0
|
||||||
|
2019-11-18,12.200000,12.200000,12.200000,12.200000,12.200000,0
|
||||||
|
2019-11-19,12.200000,12.200000,12.200000,12.200000,12.200000,0
|
||||||
|
2019-11-20,12.190000,12.190000,12.190000,12.190000,12.190000,0
|
||||||
|
2019-11-21,12.160000,12.160000,12.160000,12.160000,12.160000,0
|
||||||
|
2019-11-22,12.190000,12.190000,12.190000,12.190000,12.190000,0
|
||||||
|
2019-11-25,12.220000,12.220000,12.220000,12.220000,12.220000,0
|
||||||
|
2019-11-26,12.220000,12.220000,12.220000,12.220000,12.220000,0
|
||||||
|
2019-11-27,12.220000,12.220000,12.220000,12.220000,12.220000,0
|
||||||
|
2019-11-29,12.220000,12.220000,12.220000,12.220000,12.220000,0
|
||||||
|
2019-12-02,12.170000,12.170000,12.170000,12.170000,12.170000,0
|
||||||
|
2019-12-03,12.090000,12.090000,12.090000,12.090000,12.090000,0
|
||||||
|
2019-12-04,12.150000,12.150000,12.150000,12.150000,12.150000,0
|
||||||
|
2019-12-05,12.150000,12.150000,12.150000,12.150000,12.150000,0
|
||||||
|
2019-12-06,12.160000,12.160000,12.160000,12.160000,12.160000,0
|
||||||
|
2019-12-09,11.950000,11.950000,11.950000,11.950000,11.950000,0
|
||||||
|
2019-12-10,11.950000,11.950000,11.950000,11.950000,11.950000,0
|
||||||
|
2019-12-11,11.950000,11.950000,11.950000,11.950000,11.950000,0
|
||||||
|
2019-12-12,11.960000,11.960000,11.960000,11.960000,11.960000,0
|
||||||
|
2019-12-13,11.990000,11.990000,11.990000,11.990000,11.990000,0
|
||||||
|
2019-12-16,12.000000,12.000000,12.000000,12.000000,12.000000,0
|
||||||
|
2019-12-17,12.000000,12.000000,12.000000,12.000000,12.000000,0
|
||||||
|
2019-12-18,12.000000,12.000000,12.000000,12.000000,12.000000,0
|
||||||
|
2019-12-19,12.010000,12.010000,12.010000,12.010000,12.010000,0
|
||||||
|
2019-12-20,12.000000,12.000000,12.000000,12.000000,12.000000,0
|
||||||
|
2019-12-23,12.000000,12.000000,12.000000,12.000000,12.000000,0
|
||||||
|
2019-12-24,12.010000,12.010000,12.010000,12.010000,12.010000,0
|
||||||
|
2019-12-26,12.010000,12.010000,12.010000,12.010000,12.010000,0
|
||||||
|
2019-12-27,11.990000,11.990000,11.990000,11.990000,11.990000,0
|
||||||
|
2019-12-30,11.970000,11.970000,11.970000,11.970000,11.970000,0
|
||||||
|
2019-12-31,12.000000,12.000000,12.000000,12.000000,12.000000,0
|
||||||
|
2020-01-02,12.010000,12.010000,12.010000,12.010000,12.010000,0
|
||||||
|
2020-01-03,11.970000,11.970000,11.970000,11.970000,11.970000,0
|
||||||
|
2020-01-06,11.970000,11.970000,11.970000,11.970000,11.970000,0
|
||||||
|
2020-01-07,11.980000,11.980000,11.980000,11.980000,11.980000,0
|
||||||
|
2020-01-08,12.000000,12.000000,12.000000,12.000000,12.000000,0
|
||||||
|
2020-01-09,12.010000,12.010000,12.010000,12.010000,12.010000,0
|
||||||
|
2020-01-10,12.010000,12.010000,12.010000,12.010000,12.010000,0
|
||||||
|
2020-01-13,12.050000,12.050000,12.050000,12.050000,12.050000,0
|
||||||
|
2020-01-14,12.060000,12.060000,12.060000,12.060000,12.060000,0
|
||||||
|
2020-01-15,12.060000,12.060000,12.060000,12.060000,12.060000,0
|
||||||
|
2020-01-16,12.070000,12.070000,12.070000,12.070000,12.070000,0
|
||||||
|
2020-01-17,12.070000,12.070000,12.070000,12.070000,12.070000,0
|
||||||
|
2020-01-21,12.070000,12.070000,12.070000,12.070000,12.070000,0
|
||||||
|
2020-01-22,12.070000,12.070000,12.070000,12.070000,12.070000,0
|
||||||
|
2020-01-23,12.070000,12.070000,12.070000,12.070000,12.070000,0
|
||||||
|
2020-01-24,11.990000,11.990000,11.990000,11.990000,11.990000,0
|
||||||
|
2020-01-27,11.890000,11.890000,11.890000,11.890000,11.890000,0
|
||||||
|
2020-01-28,12.020000,12.020000,12.020000,12.020000,12.020000,0
|
||||||
|
2020-01-29,12.000000,12.000000,12.000000,12.000000,12.000000,0
|
||||||
|
2020-01-30,12.000000,12.000000,12.000000,12.000000,12.000000,0
|
||||||
|
2020-01-31,11.900000,11.900000,11.900000,11.900000,11.900000,0
|
||||||
|
2020-02-03,12.010000,12.010000,12.010000,12.010000,12.010000,0
|
||||||
|
2020-02-04,12.020000,12.020000,12.020000,12.020000,12.020000,0
|
||||||
|
2020-02-05,12.030000,12.030000,12.030000,12.030000,12.030000,0
|
||||||
|
2020-02-06,12.030000,12.030000,12.030000,12.030000,12.030000,0
|
||||||
|
2020-02-07,12.020000,12.020000,12.020000,12.020000,12.020000,0
|
||||||
|
2020-02-10,12.030000,12.030000,12.030000,12.030000,12.030000,0
|
||||||
|
2020-02-11,12.030000,12.030000,12.030000,12.030000,12.030000,0
|
||||||
|
2020-02-12,12.060000,12.060000,12.060000,12.060000,12.060000,0
|
||||||
|
2020-02-13,12.060000,12.060000,12.060000,12.060000,12.060000,0
|
||||||
|
2020-02-14,12.060000,12.060000,12.060000,12.060000,12.060000,0
|
||||||
|
2020-02-18,12.050000,12.050000,12.050000,12.050000,12.050000,0
|
||||||
|
2020-02-19,12.050000,12.050000,12.050000,12.050000,12.050000,0
|
||||||
|
2020-02-20,12.040000,12.040000,12.040000,12.040000,12.040000,0
|
||||||
|
2020-02-21,12.030000,12.030000,12.030000,12.030000,12.030000,0
|
||||||
|
2020-02-24,11.750000,11.750000,11.750000,11.750000,11.750000,0
|
||||||
|
2020-02-25,11.420000,11.420000,11.420000,11.420000,11.420000,0
|
||||||
|
2020-02-26,11.340000,11.340000,11.340000,11.340000,11.340000,0
|
||||||
|
2020-02-27,10.820000,10.820000,10.820000,10.820000,10.820000,0
|
||||||
|
2020-02-28,10.800000,10.800000,10.800000,10.800000,10.800000,0
|
||||||
|
2020-03-02,11.140000,11.140000,11.140000,11.140000,11.140000,0
|
||||||
|
2020-03-03,11.020000,11.020000,11.020000,11.020000,11.020000,0
|
||||||
|
2020-03-04,11.390000,11.390000,11.390000,11.390000,11.390000,0
|
||||||
|
2020-03-05,11.420000,11.420000,11.420000,11.420000,11.420000,0
|
||||||
|
2020-03-06,11.340000,11.340000,11.340000,11.340000,11.340000,0
|
||||||
|
2020-03-09,10.580000,10.580000,10.580000,10.580000,10.580000,0
|
||||||
|
2020-03-10,10.930000,10.930000,10.930000,10.930000,10.930000,0
|
||||||
|
2020-03-11,10.680000,10.680000,10.680000,10.680000,10.680000,0
|
||||||
|
2020-03-12,9.870000,9.870000,9.870000,9.870000,9.870000,0
|
||||||
|
2020-03-13,10.630000,10.630000,10.630000,10.630000,10.630000,0
|
||||||
|
2020-03-16,9.410000,9.410000,9.410000,9.410000,9.410000,0
|
||||||
|
2020-03-17,9.830000,9.830000,9.830000,9.830000,9.830000,0
|
||||||
|
2020-03-18,9.410000,9.410000,9.410000,9.410000,9.410000,0
|
||||||
|
2020-03-19,9.510000,9.510000,9.510000,9.510000,9.510000,0
|
||||||
|
2020-03-20,9.240000,9.240000,9.240000,9.240000,9.240000,0
|
||||||
|
2020-03-23,9.040000,9.040000,9.040000,9.040000,9.040000,0
|
||||||
|
2020-03-24,9.840000,9.840000,9.840000,9.840000,9.840000,0
|
||||||
|
2020-03-25,9.870000,9.870000,9.870000,9.870000,9.870000,0
|
||||||
|
2020-03-26,10.280000,10.280000,10.280000,10.280000,10.280000,0
|
||||||
|
2020-03-27,10.210000,10.210000,10.210000,10.210000,10.210000,0
|
||||||
|
2020-03-30,10.240000,10.240000,10.240000,10.240000,10.240000,0
|
||||||
|
2020-03-31,10.230000,10.230000,10.230000,10.230000,10.230000,0
|
||||||
|
2020-04-01,9.770000,9.770000,9.770000,9.770000,9.770000,0
|
||||||
|
2020-04-02,9.980000,9.980000,9.980000,9.980000,9.980000,0
|
||||||
|
2020-04-03,9.960000,9.960000,9.960000,9.960000,9.960000,0
|
||||||
|
2020-04-06,10.170000,10.170000,10.170000,10.170000,10.170000,0
|
||||||
|
2020-04-07,10.180000,10.180000,10.180000,10.180000,10.180000,0
|
||||||
|
2020-04-08,9.940000,9.940000,9.940000,9.940000,9.940000,0
|
||||||
|
2020-04-09,9.760000,9.760000,9.760000,9.760000,9.760000,0
|
||||||
|
2020-04-13,9.890000,9.890000,9.890000,9.890000,9.890000,0
|
||||||
|
2020-04-14,9.590000,9.590000,9.590000,9.590000,9.590000,0
|
||||||
|
2020-04-15,9.820000,9.820000,9.820000,9.820000,9.820000,0
|
||||||
|
2020-04-16,9.820000,9.820000,9.820000,9.820000,9.820000,0
|
||||||
|
2020-04-17,9.820000,9.820000,9.820000,9.820000,9.820000,0
|
||||||
|
2020-04-20,9.860000,9.860000,9.860000,9.860000,9.860000,0
|
||||||
|
2020-04-21,9.900000,9.900000,9.900000,9.900000,9.900000,0
|
||||||
|
2020-04-22,10.060000,10.060000,10.060000,10.060000,10.060000,0
|
||||||
|
2020-04-23,10.060000,10.060000,10.060000,10.060000,10.060000,0
|
||||||
|
2020-04-24,10.010000,10.010000,10.010000,10.010000,10.010000,0
|
||||||
|
2020-04-27,9.820000,9.820000,9.820000,9.820000,9.820000,0
|
||||||
|
2020-04-28,9.770000,9.770000,9.770000,9.770000,9.770000,0
|
||||||
|
2020-04-29,9.550000,9.550000,9.550000,9.550000,9.550000,0
|
||||||
|
2020-04-30,9.700000,9.700000,9.700000,9.700000,9.700000,0
|
||||||
|
2020-05-01,9.820000,9.820000,9.820000,9.820000,9.820000,0
|
||||||
|
2020-05-04,9.860000,9.860000,9.860000,9.860000,9.860000,0
|
||||||
|
2020-05-05,9.910000,9.910000,9.910000,9.910000,9.910000,0
|
||||||
|
2020-05-06,9.920000,9.920000,9.920000,9.920000,9.920000,0
|
||||||
|
2020-05-07,9.910000,9.910000,9.910000,9.910000,9.910000,0
|
||||||
|
2020-05-08,9.870000,9.870000,9.870000,9.870000,9.870000,0
|
||||||
|
2020-05-11,9.890000,9.890000,9.890000,9.890000,9.890000,0
|
||||||
|
2020-05-12,10.140000,10.140000,10.140000,10.140000,10.140000,0
|
||||||
|
2020-05-13,9.920000,9.920000,9.920000,9.920000,9.920000,0
|
||||||
|
2020-05-14,10.010000,10.010000,10.010000,10.010000,10.010000,0
|
||||||
|
2020-05-15,10.040000,10.040000,10.040000,10.040000,10.040000,0
|
||||||
|
2020-05-18,9.930000,9.930000,9.930000,9.930000,9.930000,0
|
||||||
|
2020-05-19,10.030000,10.030000,10.030000,10.030000,10.030000,0
|
||||||
|
2020-05-20,9.890000,9.890000,9.890000,9.890000,9.890000,0
|
||||||
|
2020-05-21,9.920000,9.920000,9.920000,9.920000,9.920000,0
|
||||||
|
2020-05-22,9.890000,9.890000,9.890000,9.890000,9.890000,0
|
||||||
|
2020-05-26,9.800000,9.800000,9.800000,9.800000,9.800000,0
|
||||||
|
2020-05-27,9.660000,9.660000,9.660000,9.660000,9.660000,0
|
||||||
|
2020-05-28,9.720000,9.720000,9.720000,9.720000,9.720000,0
|
||||||
|
2020-05-29,9.750000,9.750000,9.750000,9.750000,9.750000,0
|
||||||
|
2020-06-01,9.740000,9.740000,9.740000,9.740000,9.740000,0
|
||||||
|
2020-06-02,9.690000,9.690000,9.690000,9.690000,9.690000,0
|
||||||
|
2020-06-03,9.570000,9.570000,9.570000,9.570000,9.570000,0
|
||||||
|
2020-06-04,9.570000,9.570000,9.570000,9.570000,9.570000,0
|
||||||
|
2020-06-05,9.380000,9.380000,9.380000,9.380000,9.380000,0
|
||||||
|
2020-06-08,9.260000,9.260000,9.260000,9.260000,9.260000,0
|
||||||
|
2020-06-09,9.350000,9.350000,9.350000,9.350000,9.350000,0
|
||||||
|
2020-06-10,9.420000,9.420000,9.420000,9.420000,9.420000,0
|
||||||
|
2020-06-11,9.370000,9.370000,9.370000,9.370000,9.370000,0
|
||||||
|
2020-06-12,9.430000,9.430000,9.430000,9.430000,9.430000,0
|
||||||
|
2020-06-15,9.490000,9.490000,9.490000,9.490000,9.490000,0
|
||||||
|
2020-06-16,9.560000,9.560000,9.560000,9.560000,9.560000,0
|
||||||
|
2020-06-17,9.610000,9.610000,9.610000,9.610000,9.610000,0
|
||||||
|
2020-06-18,9.630000,9.630000,9.630000,9.630000,9.630000,0
|
||||||
|
2020-06-19,9.610000,9.610000,9.610000,9.610000,9.610000,0
|
||||||
|
2020-06-22,9.610000,9.610000,9.610000,9.610000,9.610000,0
|
||||||
|
2020-06-23,9.610000,9.610000,9.610000,9.610000,9.610000,0
|
||||||
|
2020-06-24,9.760000,9.760000,9.760000,9.760000,9.760000,0
|
||||||
|
2020-06-25,9.880000,9.880000,9.880000,9.880000,9.880000,0
|
||||||
|
2020-06-26,9.810000,9.810000,9.810000,9.810000,9.810000,0
|
||||||
|
2020-06-29,9.970000,9.970000,9.970000,9.970000,9.970000,0
|
||||||
|
2020-06-30,10.090000,10.090000,10.090000,10.090000,10.090000,0
|
||||||
|
2020-07-01,10.100000,10.100000,10.100000,10.100000,10.100000,0
|
||||||
|
2020-07-02,10.050000,10.050000,10.050000,10.050000,10.050000,0
|
||||||
|
2020-07-06,9.970000,9.970000,9.970000,9.970000,9.970000,0
|
||||||
|
2020-07-07,10.090000,10.090000,10.090000,10.090000,10.090000,0
|
||||||
|
2020-07-08,10.080000,10.080000,10.080000,10.080000,10.080000,0
|
||||||
|
2020-07-09,10.080000,10.080000,10.080000,10.080000,10.080000,0
|
||||||
|
2020-07-10,10.080000,10.080000,10.080000,10.080000,10.080000,0
|
||||||
|
2020-07-13,10.080000,10.080000,10.080000,10.080000,10.080000,0
|
||||||
|
2020-07-14,10.060000,10.060000,10.060000,10.060000,10.060000,0
|
||||||
|
2020-07-15,10.050000,10.050000,10.050000,10.050000,10.050000,0
|
||||||
|
2020-07-16,10.090000,10.090000,10.090000,10.090000,10.090000,0
|
||||||
|
2020-07-17,10.070000,10.070000,10.070000,10.070000,10.070000,0
|
||||||
|
2020-07-20,10.160000,10.160000,10.160000,10.160000,10.160000,0
|
||||||
|
2020-07-21,10.120000,10.120000,10.120000,10.120000,10.120000,0
|
||||||
|
2020-07-22,10.110000,10.110000,10.110000,10.110000,10.110000,0
|
||||||
|
2020-07-23,10.110000,10.110000,10.110000,10.110000,10.110000,0
|
||||||
|
2020-07-24,10.060000,10.060000,10.060000,10.060000,10.060000,0
|
||||||
|
2020-07-27,10.150000,10.150000,10.150000,10.150000,10.150000,0
|
||||||
|
2020-07-28,10.140000,10.140000,10.140000,10.140000,10.140000,0
|
||||||
|
2020-07-29,10.140000,10.140000,10.140000,10.140000,10.140000,0
|
||||||
|
2020-07-30,10.140000,10.140000,10.140000,10.140000,10.140000,0
|
||||||
|
2020-07-31,10.150000,10.150000,10.150000,10.150000,10.150000,0
|
||||||
|
2020-08-03,10.200000,10.200000,10.200000,10.200000,10.200000,0
|
||||||
|
2020-08-04,10.200000,10.200000,10.200000,10.200000,10.200000,0
|
||||||
|
2020-08-05,10.200000,10.200000,10.200000,10.200000,10.200000,0
|
||||||
|
2020-08-06,10.200000,10.200000,10.200000,10.200000,10.200000,0
|
||||||
|
2020-08-07,10.200000,10.200000,10.200000,10.200000,10.200000,0
|
||||||
|
2020-08-10,10.180000,10.180000,10.180000,10.180000,10.180000,0
|
||||||
|
2020-08-11,10.130000,10.130000,10.130000,10.130000,10.130000,0
|
||||||
|
2020-08-12,10.230000,10.230000,10.230000,10.230000,10.230000,0
|
||||||
|
2020-08-13,10.230000,10.230000,10.230000,10.230000,10.230000,0
|
||||||
|
2020-08-14,10.230000,10.230000,10.230000,10.230000,10.230000,0
|
||||||
|
2020-08-17,10.230000,10.230000,10.230000,10.230000,10.230000,0
|
||||||
|
2020-08-18,10.230000,10.230000,10.230000,10.230000,10.230000,0
|
||||||
|
2020-08-19,10.230000,10.230000,10.230000,10.230000,10.230000,0
|
||||||
|
2020-08-20,10.230000,10.230000,10.230000,10.230000,10.230000,0
|
||||||
|
2020-08-21,10.230000,10.230000,10.230000,10.230000,10.230000,0
|
||||||
|
2020-08-24,10.240000,10.240000,10.240000,10.240000,10.240000,0
|
||||||
|
2020-08-25,10.240000,10.240000,10.240000,10.240000,10.240000,0
|
||||||
|
2020-08-26,10.230000,10.230000,10.230000,10.230000,10.230000,0
|
||||||
|
2020-08-27,10.230000,10.230000,10.230000,10.230000,10.230000,0
|
||||||
|
2020-08-28,10.230000,10.230000,10.230000,10.230000,10.230000,0
|
||||||
|
2020-08-31,10.230000,10.230000,10.230000,10.230000,10.230000,0
|
||||||
|
2020-09-01,10.240000,10.240000,10.240000,10.240000,10.240000,0
|
||||||
|
2020-09-02,10.240000,10.240000,10.240000,10.240000,10.240000,0
|
||||||
|
2020-09-03,10.240000,10.240000,10.240000,10.240000,10.240000,0
|
||||||
|
2020-09-04,10.140000,10.140000,10.140000,10.140000,10.140000,0
|
||||||
|
2020-09-08,10.160000,10.160000,10.160000,10.160000,10.160000,0
|
||||||
|
2020-09-09,10.160000,10.160000,10.160000,10.160000,10.160000,0
|
||||||
|
2020-09-10,10.160000,10.160000,10.160000,10.160000,10.160000,0
|
||||||
|
2020-09-11,10.130000,10.130000,10.130000,10.130000,10.130000,0
|
||||||
|
2020-09-14,10.290000,10.290000,10.290000,10.290000,10.290000,0
|
||||||
|
2020-09-15,10.300000,10.300000,10.300000,10.300000,10.300000,0
|
||||||
|
2020-09-16,10.300000,10.300000,10.300000,10.300000,10.300000,0
|
||||||
|
2020-09-17,10.300000,10.300000,10.300000,10.300000,10.300000,0
|
||||||
|
2020-09-18,10.230000,10.230000,10.230000,10.230000,10.230000,0
|
||||||
|
2020-09-21,10.210000,10.210000,10.210000,10.210000,10.210000,0
|
||||||
|
2020-09-22,10.200000,10.200000,10.200000,10.200000,10.200000,0
|
||||||
|
2020-09-23,10.130000,10.130000,10.130000,10.130000,10.130000,0
|
||||||
|
2020-09-24,10.140000,10.140000,10.140000,10.140000,10.140000,0
|
||||||
|
2020-09-25,10.220000,10.220000,10.220000,10.220000,10.220000,0
|
||||||
|
2020-09-28,10.300000,10.300000,10.300000,10.300000,10.300000,0
|
||||||
|
2020-09-29,10.300000,10.300000,10.300000,10.300000,10.300000,0
|
||||||
|
2020-09-30,10.320000,10.320000,10.320000,10.320000,10.320000,0
|
||||||
|
2020-10-01,10.350000,10.350000,10.350000,10.350000,10.350000,0
|
||||||
|
2020-10-02,10.350000,10.350000,10.350000,10.350000,10.350000,0
|
||||||
|
2020-10-05,10.370000,10.370000,10.370000,10.370000,10.370000,0
|
||||||
|
2020-10-06,10.370000,10.370000,10.370000,10.370000,10.370000,0
|
||||||
|
2020-10-07,10.420000,10.420000,10.420000,10.420000,10.420000,0
|
||||||
|
2020-10-08,10.420000,10.420000,10.420000,10.420000,10.420000,0
|
||||||
|
2020-10-09,10.420000,10.420000,10.420000,10.420000,10.420000,0
|
||||||
|
2020-10-12,10.420000,10.420000,10.420000,10.420000,10.420000,0
|
||||||
|
2020-10-13,10.420000,10.420000,10.420000,10.420000,10.420000,0
|
||||||
|
2020-10-14,10.420000,10.420000,10.420000,10.420000,10.420000,0
|
||||||
|
2020-10-15,10.420000,10.420000,10.420000,10.420000,10.420000,0
|
||||||
|
2020-10-16,10.400000,10.400000,10.400000,10.400000,10.400000,0
|
||||||
|
2020-10-19,10.370000,10.370000,10.370000,10.370000,10.370000,0
|
||||||
|
2020-10-20,10.380000,10.380000,10.380000,10.380000,10.380000,0
|
||||||
|
2020-10-21,10.380000,10.380000,10.380000,10.380000,10.380000,0
|
||||||
|
2020-10-22,10.390000,10.390000,10.390000,10.390000,10.390000,0
|
||||||
|
2020-10-23,10.390000,10.390000,10.390000,10.390000,10.390000,0
|
||||||
|
2020-10-26,10.390000,10.390000,10.390000,10.390000,10.390000,0
|
||||||
|
2020-10-27,10.390000,10.390000,10.390000,10.390000,10.390000,0
|
||||||
|
2020-10-28,10.270000,10.270000,10.270000,10.270000,10.270000,0
|
||||||
|
2020-10-29,10.270000,10.270000,10.270000,10.270000,10.270000,0
|
||||||
|
2020-10-30,10.270000,10.270000,10.270000,10.270000,10.270000,0
|
||||||
|
2020-11-02,10.270000,10.270000,10.270000,10.270000,10.270000,0
|
||||||
|
2020-11-03,10.270000,10.270000,10.270000,10.270000,10.270000,0
|
||||||
|
2020-11-04,10.260000,10.260000,10.260000,10.260000,10.260000,0
|
||||||
|
2020-11-05,10.260000,10.260000,10.260000,10.260000,10.260000,0
|
||||||
|
2020-11-06,10.260000,10.260000,10.260000,10.260000,10.260000,0
|
||||||
|
2020-11-09,10.260000,10.260000,10.260000,10.260000,10.260000,0
|
||||||
|
2020-11-10,10.260000,10.260000,10.260000,10.260000,10.260000,0
|
||||||
|
2020-11-11,10.260000,10.260000,10.260000,10.260000,10.260000,0
|
||||||
|
2020-11-12,10.260000,10.260000,10.260000,10.260000,10.260000,0
|
||||||
|
2020-11-13,10.320000,10.320000,10.320000,10.320000,10.320000,0
|
||||||
|
2020-11-16,10.320000,10.320000,10.320000,10.320000,10.320000,0
|
||||||
|
2020-11-17,10.320000,10.320000,10.320000,10.320000,10.320000,0
|
||||||
|
2020-11-18,10.320000,10.320000,10.320000,10.320000,10.320000,0
|
||||||
|
2020-11-19,10.320000,10.320000,10.320000,10.320000,10.320000,0
|
||||||
|
2020-11-20,10.300000,10.300000,10.300000,10.300000,10.300000,0
|
||||||
|
2020-11-23,10.320000,10.320000,10.320000,10.320000,10.320000,0
|
||||||
|
2020-11-24,10.320000,10.320000,10.320000,10.320000,10.320000,0
|
||||||
|
2020-11-25,10.320000,10.320000,10.320000,10.320000,10.320000,0
|
||||||
|
2020-11-27,10.310000,10.310000,10.310000,10.310000,10.310000,0
|
||||||
|
2020-11-30,10.310000,10.310000,10.310000,10.310000,10.310000,0
|
||||||
|
2020-12-01,10.330000,10.330000,10.330000,10.330000,10.330000,0
|
||||||
|
2020-12-02,10.330000,10.330000,10.330000,10.330000,10.330000,0
|
||||||
|
2020-12-03,10.330000,10.330000,10.330000,10.330000,10.330000,0
|
||||||
|
2020-12-04,10.330000,10.330000,10.330000,10.330000,10.330000,0
|
||||||
|
2020-12-07,10.330000,10.330000,10.330000,10.330000,10.330000,0
|
||||||
|
2020-12-08,10.320000,10.320000,10.320000,10.320000,10.320000,0
|
||||||
|
2020-12-09,10.320000,10.320000,10.320000,10.320000,10.320000,0
|
||||||
|
2020-12-10,10.330000,10.330000,10.330000,10.330000,10.330000,0
|
||||||
|
2020-12-11,10.320000,10.320000,10.320000,10.320000,10.320000,0
|
||||||
|
2020-12-14,10.310000,10.310000,10.310000,10.310000,10.310000,0
|
||||||
|
2020-12-15,10.340000,10.340000,10.340000,10.340000,10.340000,0
|
||||||
|
2020-12-16,10.340000,10.340000,10.340000,10.340000,10.340000,0
|
||||||
|
2020-12-17,10.340000,10.340000,10.340000,10.340000,10.340000,0
|
||||||
|
2020-12-18,10.340000,10.340000,10.340000,10.340000,10.340000,0
|
||||||
|
2020-12-21,10.340000,10.340000,10.340000,10.340000,10.340000,0
|
||||||
|
2020-12-22,10.330000,10.330000,10.330000,10.330000,10.330000,0
|
||||||
|
2020-12-23,10.340000,10.340000,10.340000,10.340000,10.340000,0
|
||||||
|
2020-12-24,10.340000,10.340000,10.340000,10.340000,10.340000,0
|
||||||
|
2020-12-28,10.330000,10.330000,10.330000,10.330000,10.330000,0
|
||||||
|
2020-12-29,10.330000,10.330000,10.330000,10.330000,10.330000,0
|
||||||
|
2020-12-30,10.350000,10.350000,10.350000,10.350000,10.350000,0
|
||||||
|
2020-12-31,10.350000,10.350000,10.350000,10.350000,10.350000,0
|
||||||
|
2021-01-04,10.350000,10.350000,10.350000,10.350000,10.350000,0
|
||||||
|
2021-01-05,10.370000,10.370000,10.370000,10.370000,10.370000,0
|
||||||
|
2021-01-06,10.370000,10.370000,10.370000,10.370000,10.370000,0
|
||||||
|
2021-01-07,10.370000,10.370000,10.370000,10.370000,10.370000,0
|
||||||
|
2021-01-08,10.370000,10.370000,10.370000,10.370000,10.370000,0
|
||||||
|
2021-01-11,10.370000,10.370000,10.370000,10.370000,10.370000,0
|
||||||
|
2021-01-12,10.370000,10.370000,10.370000,10.370000,10.370000,0
|
||||||
|
2021-01-13,10.360000,10.360000,10.360000,10.360000,10.360000,0
|
||||||
|
2021-01-14,10.360000,10.360000,10.360000,10.360000,10.360000,0
|
||||||
|
2021-01-15,10.360000,10.360000,10.360000,10.360000,10.360000,0
|
||||||
|
2021-01-19,10.370000,10.370000,10.370000,10.370000,10.370000,0
|
||||||
|
2021-01-20,10.370000,10.370000,10.370000,10.370000,10.370000,0
|
||||||
|
2021-01-21,10.370000,10.370000,10.370000,10.370000,10.370000,0
|
||||||
|
2021-01-22,10.370000,10.370000,10.370000,10.370000,10.370000,0
|
||||||
|
2021-01-25,10.370000,10.370000,10.370000,10.370000,10.370000,0
|
||||||
|
2021-01-26,10.370000,10.370000,10.370000,10.370000,10.370000,0
|
||||||
|
2021-01-27,10.360000,10.360000,10.360000,10.360000,10.360000,0
|
||||||
|
2021-01-28,10.380000,10.380000,10.380000,10.380000,10.380000,0
|
||||||
|
2021-01-29,10.380000,10.380000,10.380000,10.380000,10.380000,0
|
||||||
|
2021-02-01,10.480000,10.480000,10.480000,10.480000,10.480000,0
|
||||||
|
2021-02-02,10.510000,10.510000,10.510000,10.510000,10.510000,0
|
||||||
|
2021-02-03,10.510000,10.510000,10.510000,10.510000,10.510000,0
|
||||||
|
2021-02-04,10.510000,10.510000,10.510000,10.510000,10.510000,0
|
||||||
|
2021-02-05,10.510000,10.510000,10.510000,10.510000,10.510000,0
|
||||||
|
2021-02-08,10.500000,10.500000,10.500000,10.500000,10.500000,0
|
||||||
|
2021-02-09,10.500000,10.500000,10.500000,10.500000,10.500000,0
|
||||||
|
2021-02-10,10.500000,10.500000,10.500000,10.500000,10.500000,0
|
||||||
|
2021-02-11,10.500000,10.500000,10.500000,10.500000,10.500000,0
|
||||||
|
2021-02-12,10.500000,10.500000,10.500000,10.500000,10.500000,0
|
||||||
|
2021-02-16,10.500000,10.500000,10.500000,10.500000,10.500000,0
|
||||||
|
2021-02-17,10.500000,10.500000,10.500000,10.500000,10.500000,0
|
||||||
|
2021-02-18,10.470000,10.470000,10.470000,10.470000,10.470000,0
|
||||||
|
2021-02-19,10.470000,10.470000,10.470000,10.470000,10.470000,0
|
||||||
|
2021-02-22,10.470000,10.470000,10.470000,10.470000,10.470000,0
|
||||||
|
2021-02-23,10.460000,10.460000,10.460000,10.460000,10.460000,0
|
||||||
|
2021-02-24,10.470000,10.470000,10.470000,10.470000,10.470000,0
|
||||||
|
2021-02-25,10.420000,10.420000,10.420000,10.420000,10.420000,0
|
||||||
|
2021-02-26,10.420000,10.420000,10.420000,10.420000,10.420000,0
|
||||||
|
2021-03-01,10.500000,10.500000,10.500000,10.500000,10.500000,0
|
||||||
|
2021-03-02,10.490000,10.490000,10.490000,10.490000,10.490000,0
|
||||||
|
2021-03-03,10.490000,10.490000,10.490000,10.490000,10.490000,0
|
||||||
|
2021-03-04,10.470000,10.470000,10.470000,10.470000,10.470000,0
|
||||||
|
2021-03-05,10.560000,10.560000,10.560000,10.560000,10.560000,0
|
||||||
|
2021-03-08,10.560000,10.560000,10.560000,10.560000,10.560000,0
|
||||||
|
2021-03-09,10.620000,10.620000,10.620000,10.620000,10.620000,0
|
||||||
|
2021-03-10,10.620000,10.620000,10.620000,10.620000,10.620000,0
|
||||||
|
2021-03-11,10.620000,10.620000,10.620000,10.620000,10.620000,0
|
||||||
|
2021-03-12,10.620000,10.620000,10.620000,10.620000,10.620000,0
|
||||||
|
2021-03-15,10.610000,10.610000,10.610000,10.610000,10.610000,0
|
||||||
|
2021-03-16,10.610000,10.610000,10.610000,10.610000,10.610000,0
|
||||||
|
2021-03-17,10.620000,10.620000,10.620000,10.620000,10.620000,0
|
||||||
|
2021-03-18,10.620000,10.620000,10.620000,10.620000,10.620000,0
|
||||||
|
2021-03-19,10.640000,10.640000,10.640000,10.640000,10.640000,0
|
||||||
|
2021-03-22,10.630000,10.630000,10.630000,10.630000,10.630000,0
|
||||||
|
2021-03-23,10.580000,10.580000,10.580000,10.580000,10.580000,0
|
||||||
|
2021-03-24,10.540000,10.540000,10.540000,10.540000,10.540000,0
|
||||||
|
2021-03-25,10.580000,10.580000,10.580000,10.580000,10.580000,0
|
||||||
|
2021-03-26,10.630000,10.630000,10.630000,10.630000,10.630000,0
|
||||||
|
2021-03-29,10.590000,10.590000,10.590000,10.590000,10.590000,0
|
||||||
|
2021-03-30,10.600000,10.600000,10.600000,10.600000,10.600000,0
|
||||||
|
2021-03-31,10.640000,10.640000,10.640000,10.640000,10.640000,0
|
||||||
|
2021-04-01,10.640000,10.640000,10.640000,10.640000,10.640000,0
|
||||||
|
2021-04-05,10.640000,10.640000,10.640000,10.640000,10.640000,0
|
||||||
|
2021-04-06,10.640000,10.640000,10.640000,10.640000,10.640000,0
|
||||||
|
2021-04-07,10.640000,10.640000,10.640000,10.640000,10.640000,0
|
||||||
|
2021-04-08,10.640000,10.640000,10.640000,10.640000,10.640000,0
|
||||||
|
2021-04-09,10.640000,10.640000,10.640000,10.640000,10.640000,0
|
||||||
|
7
overrides/frozen/amfzx.json
Normal file
7
overrides/frozen/amfzx.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"symbol": "amfzx",
|
||||||
|
"longName": "Investment Managers Series Trust - 361 Managed Futures Strategy Fund",
|
||||||
|
"freeze_date": "2021-04-09",
|
||||||
|
"created": "2026-08-31",
|
||||||
|
"reason": "yahoo-empty"
|
||||||
|
}
|
||||||
3
overrides/frozen/andrx-capitalGain.csv
Normal file
3
overrides/frozen/andrx-capitalGain.csv
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
Date,Capital Gains
|
||||||
|
2014-12-19,0.282000
|
||||||
|
2017-12-20,0.015000
|
||||||
|
9
overrides/frozen/andrx-dividend.csv
Normal file
9
overrides/frozen/andrx-dividend.csv
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
Date,Dividends
|
||||||
|
2025-12-17,0.784130
|
||||||
|
2026-04-28,6.557670
|
||||||
|
2019-12-23,0.354020
|
||||||
|
2020-12-22,0.262650
|
||||||
|
2021-12-23,0.400300
|
||||||
|
2022-12-19,0.267040
|
||||||
|
2023-12-18,0.433520
|
||||||
|
2024-12-17,0.336460
|
||||||
|
1843
overrides/frozen/andrx-history.csv
Normal file
1843
overrides/frozen/andrx-history.csv
Normal file
File diff suppressed because it is too large
Load Diff
7
overrides/frozen/andrx.json
Normal file
7
overrides/frozen/andrx.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"symbol": "andrx",
|
||||||
|
"longName": "AQR Funds - AQR International Defensive Style Fund",
|
||||||
|
"freeze_date": "2026-05-01",
|
||||||
|
"created": "2026-08-31",
|
||||||
|
"reason": "yahoo-empty"
|
||||||
|
}
|
||||||
14
overrides/frozen/arwdx-capitalGain.csv
Normal file
14
overrides/frozen/arwdx-capitalGain.csv
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
Date,Capital Gains
|
||||||
|
2019-12-30,0.866000
|
||||||
|
2021-12-28,0.665000
|
||||||
|
2024-12-20,0.317000
|
||||||
|
2025-06-10,0.977000
|
||||||
|
2016-12-29,0.128000
|
||||||
|
2017-10-19,0.113000
|
||||||
|
2017-12-28,0.010000
|
||||||
|
2020-12-29,0.770000
|
||||||
|
2022-12-28,0.254000
|
||||||
|
2023-12-21,0.247000
|
||||||
|
2014-12-30,0.048000
|
||||||
|
2015-12-30,0.155000
|
||||||
|
2018-12-27,0.556000
|
||||||
|
16
overrides/frozen/arwdx-dividend.csv
Normal file
16
overrides/frozen/arwdx-dividend.csv
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
Date,Dividends
|
||||||
|
2014-12-30,0.284000
|
||||||
|
2017-10-19,0.218000
|
||||||
|
2021-12-28,1.273000
|
||||||
|
2023-12-21,0.593000
|
||||||
|
2025-06-10,1.092000
|
||||||
|
2017-12-28,0.179000
|
||||||
|
2018-12-31,0.421000
|
||||||
|
2020-12-29,0.991000
|
||||||
|
2015-12-30,0.343000
|
||||||
|
2016-12-29,0.277000
|
||||||
|
2024-12-20,0.743000
|
||||||
|
2013-12-30,0.147000
|
||||||
|
2018-12-27,0.977000
|
||||||
|
2019-12-30,1.142000
|
||||||
|
2022-12-28,0.622000
|
||||||
|
2
overrides/frozen/arwdx-history.csv
Normal file
2
overrides/frozen/arwdx-history.csv
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
Date,Open,High,Low,Close,Adj Close,Volume
|
||||||
|
2025-09-23,8.650000,8.650000,8.650000,8.650000,8.650000,0
|
||||||
|
7
overrides/frozen/arwdx.json
Normal file
7
overrides/frozen/arwdx.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"symbol": "arwdx",
|
||||||
|
"longName": "American Century Asset Allocation Portfolios, Inc. - One Choice 2025 Portfolio",
|
||||||
|
"freeze_date": "2025-09-23",
|
||||||
|
"created": "2026-08-31",
|
||||||
|
"reason": "yahoo-empty"
|
||||||
|
}
|
||||||
5
overrides/frozen/atezx-capitalGain.csv
Normal file
5
overrides/frozen/atezx-capitalGain.csv
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
Date,Capital Gains
|
||||||
|
2021-12-07,17.691000
|
||||||
|
2022-12-06,2.947000
|
||||||
|
2024-12-10,11.705000
|
||||||
|
2025-12-09,18.145000
|
||||||
|
6
overrides/frozen/atezx-dividend.csv
Normal file
6
overrides/frozen/atezx-dividend.csv
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
Date,Dividends
|
||||||
|
2022-12-06,3.798000
|
||||||
|
2023-12-05,0.469000
|
||||||
|
2024-12-10,11.705000
|
||||||
|
2025-12-09,18.145000
|
||||||
|
2021-12-07,17.691000
|
||||||
|
2
overrides/frozen/atezx-history.csv
Normal file
2
overrides/frozen/atezx-history.csv
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
Date,Open,High,Low,Close,Adj Close,Volume
|
||||||
|
2026-07-17,137.520004,137.520004,137.520004,137.520004,137.520004,0
|
||||||
|
7
overrides/frozen/atezx.json
Normal file
7
overrides/frozen/atezx.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"symbol": "atezx",
|
||||||
|
"longName": "AB Sustainable Global Thematic Z",
|
||||||
|
"freeze_date": "2026-07-17",
|
||||||
|
"created": "2026-08-31",
|
||||||
|
"reason": "yahoo-empty"
|
||||||
|
}
|
||||||
491
overrides/frozen/atmdx-dividend.csv
Normal file
491
overrides/frozen/atmdx-dividend.csv
Normal file
|
|
@ -0,0 +1,491 @@
|
||||||
|
Date,Dividends,ctime
|
||||||
|
2014-07-31,0.016,2017-08-22
|
||||||
|
2011-02-28,0.006,2017-08-22
|
||||||
|
2011-08-31,0.008,2017-08-22
|
||||||
|
2017-03-31,0.02,2017-08-22
|
||||||
|
2016-12-30,0.022,2017-08-22
|
||||||
|
2017-06-30,0.024,2017-08-22
|
||||||
|
2009-06-30,0.009,2017-08-22
|
||||||
|
2011-12-28,0.023,2017-08-22
|
||||||
|
2011-12-30,0.007,2017-08-22
|
||||||
|
2013-06-28,0.003,2017-08-22
|
||||||
|
2012-08-31,0.006,2017-08-22
|
||||||
|
2015-04-30,0.014,2017-08-22
|
||||||
|
2016-08-31,0.018,2017-08-22
|
||||||
|
2012-02-29,0.012,2017-08-22
|
||||||
|
2013-04-30,0.011,2017-08-22
|
||||||
|
2013-10-31,0.004,2017-08-22
|
||||||
|
2013-12-31,0.008,2017-08-22
|
||||||
|
2012-03-30,0.014,2017-08-22
|
||||||
|
2011-01-31,0.008,2017-08-22
|
||||||
|
2015-11-30,0.016,2017-08-22
|
||||||
|
2012-06-29,0.013,2017-08-22
|
||||||
|
2015-08-31,0.015,2017-08-22
|
||||||
|
2016-02-29,0.019,2017-08-22
|
||||||
|
2012-09-28,0.003,2017-08-22
|
||||||
|
2011-11-30,0.008,2017-08-22
|
||||||
|
2015-03-31,0.007,2017-08-22
|
||||||
|
2012-04-30,0.015,2017-08-22
|
||||||
|
2009-05-29,0.001,2017-08-22
|
||||||
|
2012-10-31,0.003,2017-08-22
|
||||||
|
2015-06-30,0.015,2017-08-22
|
||||||
|
2011-03-31,0.007,2017-08-22
|
||||||
|
2016-10-31,0.019,2017-08-22
|
||||||
|
2012-11-30,0.002,2017-08-22
|
||||||
|
2014-05-30,0.012,2017-08-22
|
||||||
|
2009-12-31,0.016,2017-08-22
|
||||||
|
2011-06-30,0.008,2017-08-22
|
||||||
|
2013-12-27,0.014,2017-08-22
|
||||||
|
2016-11-30,0.02,2017-08-22
|
||||||
|
2014-08-29,0.015,2017-08-22
|
||||||
|
2015-12-29,0.263,2017-08-22
|
||||||
|
2015-12-31,0.019,2017-08-22
|
||||||
|
2010-02-26,0.012,2017-08-22
|
||||||
|
2013-05-31,0.007,2017-08-22
|
||||||
|
2013-11-29,0.006,2017-08-22
|
||||||
|
2014-09-30,0.016,2017-08-22
|
||||||
|
2011-10-31,0.009,2017-08-22
|
||||||
|
2017-05-31,0.021,2017-08-22
|
||||||
|
2009-12-09,0.043,2017-08-22
|
||||||
|
2013-08-30,0.001,2017-08-22
|
||||||
|
2014-02-28,0.007,2017-08-22
|
||||||
|
2010-09-30,0.008,2017-08-22
|
||||||
|
2014-01-31,0.008,2017-08-22
|
||||||
|
2010-01-29,0.018,2017-08-22
|
||||||
|
2010-07-30,0.008,2017-08-22
|
||||||
|
2014-10-31,0.017,2017-08-22
|
||||||
|
2013-03-28,0.004,2017-08-22
|
||||||
|
2014-11-28,0.014,2017-08-22
|
||||||
|
2013-09-30,0.003,2017-08-22
|
||||||
|
2010-10-29,0.008,2017-08-22
|
||||||
|
2016-05-31,0.018,2017-08-22
|
||||||
|
2010-12-08,0.007,2017-08-22
|
||||||
|
2015-02-27,0.006,2017-08-22
|
||||||
|
2009-09-30,0.014,2017-08-22
|
||||||
|
2010-11-30,0.011,2017-08-22
|
||||||
|
2012-05-31,0.015,2017-08-22
|
||||||
|
2013-07-31,0.001,2017-08-22
|
||||||
|
2010-08-31,0.007,2017-08-22
|
||||||
|
2016-03-31,0.02,2017-08-22
|
||||||
|
2010-05-28,0.013,2017-08-22
|
||||||
|
2017-07-31,0.02,2017-08-22
|
||||||
|
2009-07-31,0.023,2017-08-22
|
||||||
|
2016-06-30,0.018,2017-08-22
|
||||||
|
2015-05-29,0.016,2017-08-22
|
||||||
|
2009-10-30,0.027,2017-08-22
|
||||||
|
2012-12-27,0.068,2017-08-22
|
||||||
|
2014-04-30,0.007,2017-08-22
|
||||||
|
2011-05-31,0.012,2017-08-22
|
||||||
|
2009-08-31,0.015,2017-08-22
|
||||||
|
2016-01-29,0.017,2017-08-22
|
||||||
|
2016-07-29,0.017,2017-08-22
|
||||||
|
2013-02-28,0.006,2017-08-22
|
||||||
|
2014-12-29,0.111,2017-08-22
|
||||||
|
2014-12-31,0.01,2017-08-22
|
||||||
|
2012-01-31,0.005,2017-08-22
|
||||||
|
2012-07-31,0.007,2017-08-22
|
||||||
|
2015-09-30,0.017,2017-08-22
|
||||||
|
2017-04-28,0.019,2017-08-22
|
||||||
|
2011-09-30,0.009,2017-08-22
|
||||||
|
2017-02-28,0.017,2017-08-22
|
||||||
|
2014-03-31,0.005,2017-08-22
|
||||||
|
2011-04-29,0.009,2017-08-22
|
||||||
|
2015-07-31,0.015,2017-08-22
|
||||||
|
2014-06-30,0.016,2017-08-22
|
||||||
|
2011-07-29,0.006,2017-08-22
|
||||||
|
2010-03-31,0.011,2017-08-22
|
||||||
|
2015-10-30,0.017,2017-08-22
|
||||||
|
2010-06-30,0.008,2017-08-22
|
||||||
|
2010-12-31,0.01,2017-08-22
|
||||||
|
2017-01-31,0.017,2017-08-22
|
||||||
|
2009-11-30,0.014,2017-08-22
|
||||||
|
2016-04-29,0.018,2017-08-22
|
||||||
|
2017-09-29,0.023,2017-10-20 09:54:16
|
||||||
|
2012-08-31,0.006,2017-10-20 09:54:16
|
||||||
|
2015-04-30,0.014,2017-10-20 09:54:16
|
||||||
|
2016-08-31,0.018,2017-10-20 09:54:16
|
||||||
|
2012-02-29,0.012,2017-10-20 09:54:16
|
||||||
|
2013-04-30,0.011,2017-10-20 09:54:16
|
||||||
|
2013-10-31,0.004,2017-10-20 09:54:16
|
||||||
|
2013-12-31,0.008,2017-10-20 09:54:16
|
||||||
|
2012-03-30,0.014,2017-10-20 09:54:16
|
||||||
|
2011-01-31,0.008,2017-10-20 09:54:16
|
||||||
|
2015-11-30,0.016,2017-10-20 09:54:16
|
||||||
|
2012-06-29,0.013,2017-10-20 09:54:16
|
||||||
|
2015-08-31,0.015,2017-10-20 09:54:16
|
||||||
|
2016-02-29,0.019,2017-10-20 09:54:16
|
||||||
|
2012-09-28,0.003,2017-10-20 09:54:16
|
||||||
|
2011-11-30,0.008,2017-10-20 09:54:16
|
||||||
|
2015-03-31,0.007,2017-10-20 09:54:16
|
||||||
|
2012-04-30,0.015,2017-10-20 09:54:16
|
||||||
|
2009-05-29,0.001,2017-10-20 09:54:16
|
||||||
|
2012-10-31,0.003,2017-10-20 09:54:16
|
||||||
|
2015-06-30,0.015,2017-10-20 09:54:16
|
||||||
|
2011-03-31,0.007,2017-10-20 09:54:16
|
||||||
|
2016-10-31,0.019,2017-10-20 09:54:16
|
||||||
|
2012-11-30,0.002,2017-10-20 09:54:16
|
||||||
|
2014-05-30,0.012,2017-10-20 09:54:16
|
||||||
|
2009-12-31,0.016,2017-10-20 09:54:16
|
||||||
|
2011-06-30,0.008,2017-10-20 09:54:16
|
||||||
|
2013-12-27,0.014,2017-10-20 09:54:16
|
||||||
|
2016-11-30,0.02,2017-10-20 09:54:16
|
||||||
|
2014-08-29,0.015,2017-10-20 09:54:16
|
||||||
|
2015-12-29,0.263,2017-10-20 09:54:16
|
||||||
|
2015-12-31,0.019,2017-10-20 09:54:16
|
||||||
|
2010-02-26,0.012,2017-10-20 09:54:16
|
||||||
|
2013-05-31,0.007,2017-10-20 09:54:16
|
||||||
|
2013-11-29,0.006,2017-10-20 09:54:16
|
||||||
|
2014-09-30,0.016,2017-10-20 09:54:16
|
||||||
|
2011-10-31,0.009,2017-10-20 09:54:16
|
||||||
|
2017-05-31,0.021,2017-10-20 09:54:16
|
||||||
|
2009-12-09,0.043,2017-10-20 09:54:16
|
||||||
|
2013-08-30,0.001,2017-10-20 09:54:16
|
||||||
|
2014-02-28,0.007,2017-10-20 09:54:16
|
||||||
|
2010-09-30,0.008,2017-10-20 09:54:16
|
||||||
|
2014-01-31,0.008,2017-10-20 09:54:16
|
||||||
|
2010-01-29,0.018,2017-10-20 09:54:16
|
||||||
|
2010-07-30,0.008,2017-10-20 09:54:16
|
||||||
|
2014-10-31,0.017,2017-10-20 09:54:16
|
||||||
|
2013-03-28,0.004,2017-10-20 09:54:16
|
||||||
|
2014-11-28,0.014,2017-10-20 09:54:16
|
||||||
|
2013-09-30,0.003,2017-10-20 09:54:16
|
||||||
|
2010-10-29,0.008,2017-10-20 09:54:16
|
||||||
|
2016-05-31,0.018,2017-10-20 09:54:16
|
||||||
|
2010-12-08,0.007,2017-10-20 09:54:16
|
||||||
|
2015-02-27,0.006,2017-10-20 09:54:16
|
||||||
|
2009-09-30,0.014,2017-10-20 09:54:16
|
||||||
|
2010-11-30,0.011,2017-10-20 09:54:16
|
||||||
|
2012-05-31,0.015,2017-10-20 09:54:16
|
||||||
|
2013-07-31,0.001,2017-10-20 09:54:16
|
||||||
|
2010-08-31,0.007,2017-10-20 09:54:16
|
||||||
|
2016-03-31,0.02,2017-10-20 09:54:16
|
||||||
|
2010-05-28,0.013,2017-10-20 09:54:16
|
||||||
|
2017-07-31,0.02,2017-10-20 09:54:16
|
||||||
|
2009-07-31,0.023,2017-10-20 09:54:16
|
||||||
|
2016-06-30,0.018,2017-10-20 09:54:16
|
||||||
|
2015-05-29,0.016,2017-10-20 09:54:16
|
||||||
|
2009-10-30,0.027,2017-10-20 09:54:16
|
||||||
|
2012-12-27,0.068,2017-10-20 09:54:16
|
||||||
|
2014-04-30,0.007,2017-10-20 09:54:16
|
||||||
|
2011-05-31,0.012,2017-10-20 09:54:16
|
||||||
|
2009-08-31,0.015,2017-10-20 09:54:16
|
||||||
|
2016-01-29,0.017,2017-10-20 09:54:16
|
||||||
|
2016-07-29,0.017,2017-10-20 09:54:16
|
||||||
|
2013-02-28,0.006,2017-10-20 09:54:16
|
||||||
|
2014-12-29,0.111,2017-10-20 09:54:16
|
||||||
|
2014-12-31,0.01,2017-10-20 09:54:16
|
||||||
|
2012-01-31,0.005,2017-10-20 09:54:16
|
||||||
|
2012-07-31,0.007,2017-10-20 09:54:16
|
||||||
|
2015-09-30,0.017,2017-10-20 09:54:16
|
||||||
|
2017-04-28,0.019,2017-10-20 09:54:16
|
||||||
|
2011-09-30,0.009,2017-10-20 09:54:16
|
||||||
|
2017-02-28,0.017,2017-10-20 09:54:16
|
||||||
|
2014-03-31,0.005,2017-10-20 09:54:16
|
||||||
|
2011-04-29,0.009,2017-10-20 09:54:16
|
||||||
|
2015-07-31,0.015,2017-10-20 09:54:16
|
||||||
|
2014-06-30,0.016,2017-10-20 09:54:16
|
||||||
|
2011-07-29,0.006,2017-10-20 09:54:16
|
||||||
|
2010-03-31,0.011,2017-10-20 09:54:16
|
||||||
|
2015-10-30,0.017,2017-10-20 09:54:16
|
||||||
|
2017-08-31,0.021,2017-10-20 09:54:16
|
||||||
|
2010-06-30,0.008,2017-10-20 09:54:16
|
||||||
|
2010-12-31,0.01,2017-10-20 09:54:16
|
||||||
|
2017-01-31,0.017,2017-10-20 09:54:16
|
||||||
|
2009-11-30,0.014,2017-10-20 09:54:16
|
||||||
|
2016-04-29,0.018,2017-10-20 09:54:16
|
||||||
|
2017-10-31,0.022,2017-11-15 07:55:39
|
||||||
|
2012-02-29,0.012,2017-11-15 07:55:39
|
||||||
|
2013-04-30,0.011,2017-11-15 07:55:39
|
||||||
|
2013-10-31,0.004,2017-11-15 07:55:39
|
||||||
|
2013-12-31,0.008,2017-11-15 07:55:39
|
||||||
|
2012-03-30,0.014,2017-11-15 07:55:39
|
||||||
|
2011-01-31,0.008,2017-11-15 07:55:39
|
||||||
|
2015-11-30,0.016,2017-11-15 07:55:39
|
||||||
|
2012-06-29,0.013,2017-11-15 07:55:39
|
||||||
|
2015-08-31,0.015,2017-11-15 07:55:39
|
||||||
|
2016-02-29,0.019,2017-11-15 07:55:39
|
||||||
|
2012-09-28,0.003,2017-11-15 07:55:39
|
||||||
|
2011-11-30,0.008,2017-11-15 07:55:39
|
||||||
|
2015-03-31,0.007,2017-11-15 07:55:39
|
||||||
|
2012-04-30,0.015,2017-11-15 07:55:39
|
||||||
|
2009-05-29,0.001,2017-11-15 07:55:39
|
||||||
|
2012-10-31,0.003,2017-11-15 07:55:39
|
||||||
|
2015-06-30,0.015,2017-11-15 07:55:39
|
||||||
|
2011-03-31,0.007,2017-11-15 07:55:39
|
||||||
|
2016-10-31,0.019,2017-11-15 07:55:39
|
||||||
|
2012-11-30,0.002,2017-11-15 07:55:39
|
||||||
|
2014-05-30,0.012,2017-11-15 07:55:39
|
||||||
|
2009-12-31,0.016,2017-11-15 07:55:39
|
||||||
|
2011-06-30,0.008,2017-11-15 07:55:39
|
||||||
|
2013-12-27,0.014,2017-11-15 07:55:39
|
||||||
|
2016-11-30,0.02,2017-11-15 07:55:39
|
||||||
|
2014-08-29,0.015,2017-11-15 07:55:39
|
||||||
|
2015-12-29,0.263,2017-11-15 07:55:39
|
||||||
|
2015-12-31,0.019,2017-11-15 07:55:39
|
||||||
|
2010-02-26,0.012,2017-11-15 07:55:39
|
||||||
|
2013-05-31,0.007,2017-11-15 07:55:39
|
||||||
|
2013-11-29,0.006,2017-11-15 07:55:39
|
||||||
|
2014-09-30,0.016,2017-11-15 07:55:39
|
||||||
|
2011-10-31,0.009,2017-11-15 07:55:39
|
||||||
|
2017-05-31,0.021,2017-11-15 07:55:39
|
||||||
|
2009-12-09,0.043,2017-11-15 07:55:39
|
||||||
|
2013-08-30,0.001,2017-11-15 07:55:39
|
||||||
|
2014-02-28,0.007,2017-11-15 07:55:39
|
||||||
|
2010-09-30,0.008,2017-11-15 07:55:39
|
||||||
|
2014-01-31,0.008,2017-11-15 07:55:39
|
||||||
|
2010-01-29,0.018,2017-11-15 07:55:39
|
||||||
|
2010-07-30,0.008,2017-11-15 07:55:39
|
||||||
|
2014-10-31,0.017,2017-11-15 07:55:39
|
||||||
|
2013-03-28,0.004,2017-11-15 07:55:39
|
||||||
|
2014-11-28,0.014,2017-11-15 07:55:39
|
||||||
|
2013-09-30,0.003,2017-11-15 07:55:39
|
||||||
|
2010-10-29,0.008,2017-11-15 07:55:39
|
||||||
|
2016-05-31,0.018,2017-11-15 07:55:39
|
||||||
|
2010-12-08,0.007,2017-11-15 07:55:39
|
||||||
|
2015-02-27,0.006,2017-11-15 07:55:39
|
||||||
|
2009-09-30,0.014,2017-11-15 07:55:39
|
||||||
|
2010-11-30,0.011,2017-11-15 07:55:39
|
||||||
|
2012-05-31,0.015,2017-11-15 07:55:39
|
||||||
|
2013-07-31,0.001,2017-11-15 07:55:39
|
||||||
|
2010-08-31,0.007,2017-11-15 07:55:39
|
||||||
|
2016-03-31,0.02,2017-11-15 07:55:39
|
||||||
|
2010-05-28,0.013,2017-11-15 07:55:39
|
||||||
|
2017-07-31,0.02,2017-11-15 07:55:39
|
||||||
|
2009-07-31,0.023,2017-11-15 07:55:39
|
||||||
|
2016-06-30,0.018,2017-11-15 07:55:39
|
||||||
|
2015-05-29,0.016,2017-11-15 07:55:39
|
||||||
|
2009-10-30,0.027,2017-11-15 07:55:39
|
||||||
|
2012-12-27,0.068,2017-11-15 07:55:39
|
||||||
|
2014-04-30,0.007,2017-11-15 07:55:39
|
||||||
|
2011-05-31,0.012,2017-11-15 07:55:39
|
||||||
|
2009-08-31,0.015,2017-11-15 07:55:39
|
||||||
|
2016-01-29,0.017,2017-11-15 07:55:39
|
||||||
|
2016-07-29,0.017,2017-11-15 07:55:39
|
||||||
|
2013-02-28,0.006,2017-11-15 07:55:39
|
||||||
|
2014-12-29,0.111,2017-11-15 07:55:39
|
||||||
|
2014-12-31,0.01,2017-11-15 07:55:39
|
||||||
|
2012-01-31,0.005,2017-11-15 07:55:39
|
||||||
|
2012-07-31,0.007,2017-11-15 07:55:39
|
||||||
|
2015-09-30,0.017,2017-11-15 07:55:39
|
||||||
|
2017-04-28,0.019,2017-11-15 07:55:39
|
||||||
|
2011-09-30,0.009,2017-11-15 07:55:39
|
||||||
|
2017-02-28,0.017,2017-11-15 07:55:39
|
||||||
|
2014-03-31,0.005,2017-11-15 07:55:39
|
||||||
|
2011-04-29,0.009,2017-11-15 07:55:39
|
||||||
|
2015-07-31,0.015,2017-11-15 07:55:39
|
||||||
|
2014-06-30,0.016,2017-11-15 07:55:39
|
||||||
|
2011-07-29,0.006,2017-11-15 07:55:39
|
||||||
|
2010-03-31,0.011,2017-11-15 07:55:39
|
||||||
|
2015-10-30,0.017,2017-11-15 07:55:39
|
||||||
|
2017-08-31,0.021,2017-11-15 07:55:39
|
||||||
|
2010-06-30,0.008,2017-11-15 07:55:39
|
||||||
|
2010-12-31,0.01,2017-11-15 07:55:39
|
||||||
|
2017-01-31,0.017,2017-11-15 07:55:39
|
||||||
|
2009-11-30,0.014,2017-11-15 07:55:39
|
||||||
|
2016-04-29,0.018,2017-11-15 07:55:39
|
||||||
|
2017-11-30,0.023,2017-12-11 20:07:47
|
||||||
|
2014-12-29,0.111,2017-12-11 20:07:47
|
||||||
|
2014-12-31,0.01,2017-12-11 20:07:47
|
||||||
|
2012-01-31,0.005,2017-12-11 20:07:47
|
||||||
|
2012-07-31,0.007,2017-12-11 20:07:47
|
||||||
|
2015-09-30,0.017,2017-12-11 20:07:47
|
||||||
|
2017-04-28,0.019,2017-12-11 20:07:47
|
||||||
|
2011-09-30,0.009,2017-12-11 20:07:47
|
||||||
|
2017-02-28,0.017,2017-12-11 20:07:47
|
||||||
|
2014-03-31,0.005,2017-12-11 20:07:47
|
||||||
|
2011-04-29,0.009,2017-12-11 20:07:47
|
||||||
|
2015-07-31,0.015,2017-12-11 20:07:47
|
||||||
|
2014-06-30,0.016,2017-12-11 20:07:47
|
||||||
|
2011-07-29,0.006,2017-12-11 20:07:47
|
||||||
|
2010-03-31,0.011,2017-12-11 20:07:47
|
||||||
|
2015-10-30,0.017,2017-12-11 20:07:47
|
||||||
|
2017-08-31,0.021,2017-12-11 20:07:47
|
||||||
|
2010-06-30,0.008,2017-12-11 20:07:47
|
||||||
|
2010-12-31,0.01,2017-12-11 20:07:47
|
||||||
|
2017-01-31,0.017,2017-12-11 20:07:47
|
||||||
|
2009-11-30,0.014,2017-12-11 20:07:47
|
||||||
|
2016-04-29,0.018,2017-12-11 20:07:47
|
||||||
|
2017-12-27,0.192,2018-01-16 07:54:11
|
||||||
|
2012-03-30,0.014,2018-01-16 07:54:11
|
||||||
|
2011-01-31,0.008,2018-01-16 07:54:11
|
||||||
|
2017-12-29,0.026,2018-01-16 07:54:11
|
||||||
|
2015-11-30,0.016,2018-01-16 07:54:11
|
||||||
|
2012-06-29,0.013,2018-01-16 07:54:11
|
||||||
|
2015-08-31,0.015,2018-01-16 07:54:11
|
||||||
|
2016-02-29,0.019,2018-01-16 07:54:11
|
||||||
|
2012-09-28,0.003,2018-01-16 07:54:11
|
||||||
|
2011-11-30,0.008,2018-01-16 07:54:11
|
||||||
|
2015-03-31,0.007,2018-01-16 07:54:11
|
||||||
|
2012-04-30,0.015,2018-01-16 07:54:11
|
||||||
|
2009-05-29,0.001,2018-01-16 07:54:11
|
||||||
|
2012-10-31,0.003,2018-01-16 07:54:11
|
||||||
|
2015-06-30,0.015,2018-01-16 07:54:11
|
||||||
|
2011-03-31,0.007,2018-01-16 07:54:11
|
||||||
|
2016-10-31,0.019,2018-01-16 07:54:11
|
||||||
|
2012-11-30,0.002,2018-01-16 07:54:11
|
||||||
|
2014-05-30,0.012,2018-01-16 07:54:11
|
||||||
|
2009-12-31,0.016,2018-01-16 07:54:11
|
||||||
|
2011-06-30,0.008,2018-01-16 07:54:11
|
||||||
|
2013-12-27,0.014,2018-01-16 07:54:11
|
||||||
|
2016-11-30,0.02,2018-01-16 07:54:11
|
||||||
|
2014-08-29,0.015,2018-01-16 07:54:11
|
||||||
|
2015-12-29,0.263,2018-01-16 07:54:11
|
||||||
|
2015-12-31,0.019,2018-01-16 07:54:11
|
||||||
|
2010-02-26,0.012,2018-01-16 07:54:11
|
||||||
|
2013-05-31,0.007,2018-01-16 07:54:11
|
||||||
|
2013-11-29,0.006,2018-01-16 07:54:11
|
||||||
|
2014-09-30,0.016,2018-01-16 07:54:11
|
||||||
|
2011-10-31,0.009,2018-01-16 07:54:11
|
||||||
|
2017-05-31,0.021,2018-01-16 07:54:11
|
||||||
|
2009-12-09,0.043,2018-01-16 07:54:11
|
||||||
|
2013-08-30,0.001,2018-01-16 07:54:11
|
||||||
|
2014-02-28,0.007,2018-01-16 07:54:11
|
||||||
|
2010-09-30,0.008,2018-01-16 07:54:11
|
||||||
|
2014-01-31,0.008,2018-01-16 07:54:11
|
||||||
|
2010-01-29,0.018,2018-01-16 07:54:11
|
||||||
|
2010-07-30,0.008,2018-01-16 07:54:11
|
||||||
|
2014-10-31,0.017,2018-01-16 07:54:11
|
||||||
|
2013-03-28,0.004,2018-01-16 07:54:11
|
||||||
|
2014-11-28,0.014,2018-01-16 07:54:11
|
||||||
|
2013-09-30,0.003,2018-01-16 07:54:11
|
||||||
|
2010-10-29,0.008,2018-01-16 07:54:11
|
||||||
|
2016-05-31,0.018,2018-01-16 07:54:11
|
||||||
|
2010-12-08,0.007,2018-01-16 07:54:11
|
||||||
|
2015-02-27,0.006,2018-01-16 07:54:11
|
||||||
|
2009-09-30,0.014,2018-01-16 07:54:11
|
||||||
|
2010-11-30,0.011,2018-01-16 07:54:11
|
||||||
|
2012-05-31,0.015,2018-01-16 07:54:11
|
||||||
|
2013-07-31,0.001,2018-01-16 07:54:11
|
||||||
|
2010-08-31,0.007,2018-01-16 07:54:11
|
||||||
|
2016-03-31,0.02,2018-01-16 07:54:11
|
||||||
|
2010-05-28,0.013,2018-01-16 07:54:11
|
||||||
|
2017-07-31,0.02,2018-01-16 07:54:11
|
||||||
|
2009-07-31,0.023,2018-01-16 07:54:11
|
||||||
|
2016-06-30,0.018,2018-01-16 07:54:11
|
||||||
|
2015-05-29,0.016,2018-01-16 07:54:11
|
||||||
|
2009-10-30,0.027,2018-01-16 07:54:11
|
||||||
|
2012-12-27,0.068,2018-01-16 07:54:11
|
||||||
|
2014-04-30,0.007,2018-01-16 07:54:11
|
||||||
|
2011-05-31,0.012,2018-01-16 07:54:11
|
||||||
|
2009-08-31,0.015,2018-01-16 07:54:11
|
||||||
|
2016-01-29,0.017,2018-01-16 07:54:11
|
||||||
|
2016-07-29,0.017,2018-01-16 07:54:11
|
||||||
|
2013-02-28,0.006,2018-01-16 07:54:11
|
||||||
|
2017-11-30,0.023,2018-01-16 07:54:11
|
||||||
|
2014-12-29,0.111,2018-01-16 07:54:11
|
||||||
|
2014-12-31,0.01,2018-01-16 07:54:11
|
||||||
|
2012-01-31,0.005,2018-01-16 07:54:11
|
||||||
|
2012-07-31,0.007,2018-01-16 07:54:11
|
||||||
|
2015-09-30,0.017,2018-01-16 07:54:11
|
||||||
|
2017-04-28,0.019,2018-01-16 07:54:11
|
||||||
|
2011-09-30,0.009,2018-01-16 07:54:11
|
||||||
|
2017-02-28,0.017,2018-01-16 07:54:11
|
||||||
|
2014-03-31,0.005,2018-01-16 07:54:11
|
||||||
|
2011-04-29,0.009,2018-01-16 07:54:11
|
||||||
|
2015-07-31,0.015,2018-01-16 07:54:11
|
||||||
|
2014-06-30,0.016,2018-01-16 07:54:11
|
||||||
|
2011-07-29,0.006,2018-01-16 07:54:11
|
||||||
|
2010-03-31,0.011,2018-01-16 07:54:11
|
||||||
|
2015-10-30,0.017,2018-01-16 07:54:11
|
||||||
|
2017-08-31,0.021,2018-01-16 07:54:11
|
||||||
|
2010-06-30,0.008,2018-01-16 07:54:11
|
||||||
|
2010-12-31,0.01,2018-01-16 07:54:11
|
||||||
|
2017-01-31,0.017,2018-01-16 07:54:11
|
||||||
|
2009-11-30,0.014,2018-01-16 07:54:11
|
||||||
|
2016-04-29,0.018,2018-01-16 07:54:11
|
||||||
|
2018-01-31,0.027,2018-02-26 21:44:31
|
||||||
|
2009-09-30,0.014,2018-02-26 21:44:31
|
||||||
|
2010-11-30,0.011,2018-02-26 21:44:31
|
||||||
|
2012-05-31,0.015,2018-02-26 21:44:31
|
||||||
|
2013-07-31,0.001,2018-02-26 21:44:31
|
||||||
|
2010-08-31,0.007,2018-02-26 21:44:31
|
||||||
|
2016-03-31,0.02,2018-02-26 21:44:31
|
||||||
|
2010-05-28,0.013,2018-02-26 21:44:31
|
||||||
|
2017-07-31,0.02,2018-02-26 21:44:31
|
||||||
|
2009-07-31,0.023,2018-02-26 21:44:31
|
||||||
|
2016-06-30,0.018,2018-02-26 21:44:31
|
||||||
|
2015-05-29,0.016,2018-02-26 21:44:31
|
||||||
|
2009-10-30,0.027,2018-02-26 21:44:31
|
||||||
|
2012-12-27,0.068,2018-02-26 21:44:31
|
||||||
|
2014-04-30,0.007,2018-02-26 21:44:31
|
||||||
|
2011-05-31,0.012,2018-02-26 21:44:31
|
||||||
|
2009-08-31,0.015,2018-02-26 21:44:31
|
||||||
|
2016-01-29,0.017,2018-02-26 21:44:31
|
||||||
|
2016-07-29,0.017,2018-02-26 21:44:31
|
||||||
|
2013-02-28,0.006,2018-02-26 21:44:31
|
||||||
|
2017-11-30,0.023,2018-02-26 21:44:31
|
||||||
|
2014-12-29,0.111,2018-02-26 21:44:31
|
||||||
|
2014-12-31,0.01,2018-02-26 21:44:31
|
||||||
|
2012-01-31,0.005,2018-02-26 21:44:31
|
||||||
|
2012-07-31,0.007,2018-02-26 21:44:31
|
||||||
|
2015-09-30,0.017,2018-02-26 21:44:31
|
||||||
|
2017-04-28,0.019,2018-02-26 21:44:31
|
||||||
|
2011-09-30,0.009,2018-02-26 21:44:31
|
||||||
|
2017-02-28,0.017,2018-02-26 21:44:31
|
||||||
|
2014-03-31,0.005,2018-02-26 21:44:31
|
||||||
|
2011-04-29,0.009,2018-02-26 21:44:31
|
||||||
|
2015-07-31,0.015,2018-02-26 21:44:31
|
||||||
|
2014-06-30,0.016,2018-02-26 21:44:31
|
||||||
|
2011-07-29,0.006,2018-02-26 21:44:31
|
||||||
|
2010-03-31,0.011,2018-02-26 21:44:31
|
||||||
|
2015-10-30,0.017,2018-02-26 21:44:31
|
||||||
|
2017-08-31,0.021,2018-02-26 21:44:31
|
||||||
|
2010-06-30,0.008,2018-02-26 21:44:31
|
||||||
|
2010-12-31,0.01,2018-02-26 21:44:31
|
||||||
|
2017-01-31,0.017,2018-02-26 21:44:31
|
||||||
|
2009-11-30,0.014,2018-02-26 21:44:31
|
||||||
|
2016-04-29,0.018,2018-02-26 21:44:31
|
||||||
|
2018-02-28,0.025,2018-03-09 21:59:16
|
||||||
|
2014-01-31,0.008,2018-03-09 21:59:16
|
||||||
|
2010-01-29,0.018,2018-03-09 21:59:16
|
||||||
|
2010-07-30,0.008,2018-03-09 21:59:16
|
||||||
|
2014-10-31,0.017,2018-03-09 21:59:16
|
||||||
|
2013-03-28,0.004,2018-03-09 21:59:16
|
||||||
|
2014-11-28,0.014,2018-03-09 21:59:16
|
||||||
|
2013-09-30,0.003,2018-03-09 21:59:16
|
||||||
|
2010-10-29,0.008,2018-03-09 21:59:16
|
||||||
|
2016-05-31,0.018,2018-03-09 21:59:16
|
||||||
|
2010-12-08,0.007,2018-03-09 21:59:16
|
||||||
|
2015-02-27,0.006,2018-03-09 21:59:16
|
||||||
|
2018-01-31,0.027,2018-03-09 21:59:16
|
||||||
|
2009-09-30,0.014,2018-03-09 21:59:16
|
||||||
|
2010-11-30,0.011,2018-03-09 21:59:16
|
||||||
|
2012-05-31,0.015,2018-03-09 21:59:16
|
||||||
|
2013-07-31,0.001,2018-03-09 21:59:16
|
||||||
|
2010-08-31,0.007,2018-03-09 21:59:16
|
||||||
|
2016-03-31,0.02,2018-03-09 21:59:16
|
||||||
|
2010-05-28,0.013,2018-03-09 21:59:16
|
||||||
|
2017-07-31,0.02,2018-03-09 21:59:16
|
||||||
|
2009-07-31,0.023,2018-03-09 21:59:16
|
||||||
|
2016-06-30,0.018,2018-03-09 21:59:16
|
||||||
|
2015-05-29,0.016,2018-03-09 21:59:16
|
||||||
|
2009-10-30,0.027,2018-03-09 21:59:16
|
||||||
|
2012-12-27,0.068,2018-03-09 21:59:16
|
||||||
|
2014-04-30,0.007,2018-03-09 21:59:16
|
||||||
|
2011-05-31,0.012,2018-03-09 21:59:16
|
||||||
|
2009-08-31,0.015,2018-03-09 21:59:16
|
||||||
|
2016-01-29,0.017,2018-03-09 21:59:16
|
||||||
|
2016-07-29,0.017,2018-03-09 21:59:16
|
||||||
|
2013-02-28,0.006,2018-03-09 21:59:16
|
||||||
|
2017-11-30,0.023,2018-03-09 21:59:16
|
||||||
|
2014-12-29,0.111,2018-03-09 21:59:16
|
||||||
|
2014-12-31,0.01,2018-03-09 21:59:16
|
||||||
|
2012-01-31,0.005,2018-03-09 21:59:16
|
||||||
|
2012-07-31,0.007,2018-03-09 21:59:16
|
||||||
|
2015-09-30,0.017,2018-03-09 21:59:16
|
||||||
|
2017-04-28,0.019,2018-03-09 21:59:16
|
||||||
|
2011-09-30,0.009,2018-03-09 21:59:16
|
||||||
|
2017-02-28,0.017,2018-03-09 21:59:16
|
||||||
|
2014-03-31,0.005,2018-03-09 21:59:16
|
||||||
|
2011-04-29,0.009,2018-03-09 21:59:16
|
||||||
|
2015-07-31,0.015,2018-03-09 21:59:16
|
||||||
|
2014-06-30,0.016,2018-03-09 21:59:16
|
||||||
|
2011-07-29,0.006,2018-03-09 21:59:16
|
||||||
|
2010-03-31,0.011,2018-03-09 21:59:16
|
||||||
|
2015-10-30,0.017,2018-03-09 21:59:16
|
||||||
|
2017-08-31,0.021,2018-03-09 21:59:16
|
||||||
|
2010-06-30,0.008,2018-03-09 21:59:16
|
||||||
|
2010-12-31,0.01,2018-03-09 21:59:16
|
||||||
|
2017-01-31,0.017,2018-03-09 21:59:16
|
||||||
|
2009-11-30,0.014,2018-03-09 21:59:16
|
||||||
|
2016-04-29,0.018,2018-03-09 21:59:16
|
||||||
|
33583
overrides/frozen/atmdx-history.csv
Normal file
33583
overrides/frozen/atmdx-history.csv
Normal file
File diff suppressed because it is too large
Load Diff
7
overrides/frozen/atmdx.json
Normal file
7
overrides/frozen/atmdx.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"symbol": "atmdx",
|
||||||
|
"longName": "?",
|
||||||
|
"freeze_date": "2018-03-23",
|
||||||
|
"created": "2026-08-31",
|
||||||
|
"reason": "yahoo-empty"
|
||||||
|
}
|
||||||
5
overrides/frozen/avgyx-capitalGain.csv
Normal file
5
overrides/frozen/avgyx-capitalGain.csv
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
Date,Capital Gains
|
||||||
|
2021-12-20,2.743000
|
||||||
|
2016-12-23,0.029000
|
||||||
|
2017-12-22,0.817000
|
||||||
|
2019-12-23,0.331000
|
||||||
|
6
overrides/frozen/avgyx-dividend.csv
Normal file
6
overrides/frozen/avgyx-dividend.csv
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
Date,Dividends
|
||||||
|
2019-12-23,0.558100
|
||||||
|
2021-12-20,2.859500
|
||||||
|
2022-12-20,0.222000
|
||||||
|
2023-12-19,0.702600
|
||||||
|
2024-12-18,1.305000
|
||||||
|
1715
overrides/frozen/avgyx-history.csv
Normal file
1715
overrides/frozen/avgyx-history.csv
Normal file
File diff suppressed because it is too large
Load Diff
7
overrides/frozen/avgyx.json
Normal file
7
overrides/frozen/avgyx.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"symbol": "avgyx",
|
||||||
|
"longName": "BNY Mellon Advantage Funds, Inc. - BNY Mellon Dynamic Total Return Fund",
|
||||||
|
"freeze_date": "2025-10-24",
|
||||||
|
"created": "2026-08-31",
|
||||||
|
"reason": "yahoo-empty"
|
||||||
|
}
|
||||||
5
overrides/frozen/bafmx-capitalGain.csv
Normal file
5
overrides/frozen/bafmx-capitalGain.csv
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
Date,Capital Gains
|
||||||
|
2018-12-17,0.114000
|
||||||
|
2019-12-16,0.036000
|
||||||
|
2021-12-14,1.749000
|
||||||
|
2022-12-13,0.814000
|
||||||
|
5
overrides/frozen/bafmx-dividend.csv
Normal file
5
overrides/frozen/bafmx-dividend.csv
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
Date,Dividends
|
||||||
|
2019-12-16,0.035660
|
||||||
|
2021-12-14,1.749320
|
||||||
|
2022-12-13,0.813930
|
||||||
|
2025-12-15,7.440010
|
||||||
|
2
overrides/frozen/bafmx-history.csv
Normal file
2
overrides/frozen/bafmx-history.csv
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
Date,Open,High,Low,Close,Adj Close,Volume
|
||||||
|
2026-04-24,9.920400,9.920400,9.920400,9.920400,9.920400,0
|
||||||
|
7
overrides/frozen/bafmx.json
Normal file
7
overrides/frozen/bafmx.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"symbol": "bafmx",
|
||||||
|
"longName": "Brown Advisory Mid-Cap Growth Instl",
|
||||||
|
"freeze_date": "2026-04-24",
|
||||||
|
"created": "2026-08-31",
|
||||||
|
"reason": "yahoo-empty"
|
||||||
|
}
|
||||||
9
overrides/frozen/bbgpx-capitalGain.csv
Normal file
9
overrides/frozen/bbgpx-capitalGain.csv
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
Date,Capital Gains
|
||||||
|
2018-12-21,0.017000
|
||||||
|
2019-12-23,0.004000
|
||||||
|
2022-12-19,0.002000
|
||||||
|
2009-12-22,0.192000
|
||||||
|
2010-12-22,0.365000
|
||||||
|
2011-12-21,0.125000
|
||||||
|
2012-12-21,0.201000
|
||||||
|
2017-12-22,0.004000
|
||||||
|
284
overrides/frozen/bbgpx-dividend.csv
Normal file
284
overrides/frozen/bbgpx-dividend.csv
Normal file
|
|
@ -0,0 +1,284 @@
|
||||||
|
Date,Dividends
|
||||||
|
2003-10-31,0.052000
|
||||||
|
2014-02-28,0.019000
|
||||||
|
2017-11-30,0.026000
|
||||||
|
2008-12-31,0.035000
|
||||||
|
2021-02-26,0.017000
|
||||||
|
2021-07-30,0.013000
|
||||||
|
2024-06-28,0.026000
|
||||||
|
2002-12-31,0.015000
|
||||||
|
2012-07-31,0.033000
|
||||||
|
2014-07-31,0.019000
|
||||||
|
2014-08-29,0.021000
|
||||||
|
2014-10-31,0.021000
|
||||||
|
2016-06-30,0.022000
|
||||||
|
2005-05-31,0.035000
|
||||||
|
2006-11-30,0.042000
|
||||||
|
2015-06-30,0.017000
|
||||||
|
2018-08-31,0.030000
|
||||||
|
2021-08-31,0.011000
|
||||||
|
2024-03-28,0.023000
|
||||||
|
2006-03-31,0.037000
|
||||||
|
2011-08-31,0.031000
|
||||||
|
2011-10-31,0.034000
|
||||||
|
2016-04-29,0.024000
|
||||||
|
2019-04-30,0.030000
|
||||||
|
2020-07-31,0.028000
|
||||||
|
2023-01-31,0.019000
|
||||||
|
2013-05-31,0.034000
|
||||||
|
2013-07-31,0.033000
|
||||||
|
2015-01-30,0.020000
|
||||||
|
2017-02-28,0.024000
|
||||||
|
2019-10-31,0.025000
|
||||||
|
2025-09-30,0.029000
|
||||||
|
2025-10-31,0.029000
|
||||||
|
2006-01-31,0.041000
|
||||||
|
2015-07-31,0.021000
|
||||||
|
2016-02-29,0.024000
|
||||||
|
2004-10-29,0.022000
|
||||||
|
2007-12-31,0.042000
|
||||||
|
2009-12-31,0.027000
|
||||||
|
2011-12-21,0.125000
|
||||||
|
2013-03-28,0.032000
|
||||||
|
2023-07-31,0.023000
|
||||||
|
2013-04-30,0.034000
|
||||||
|
2015-08-31,0.023000
|
||||||
|
2020-10-30,0.021000
|
||||||
|
2021-03-31,0.016000
|
||||||
|
2008-11-28,0.034000
|
||||||
|
2017-10-31,0.028000
|
||||||
|
2021-12-31,0.013000
|
||||||
|
2025-03-31,0.028000
|
||||||
|
2005-09-30,0.035000
|
||||||
|
2007-10-31,0.044000
|
||||||
|
2009-06-30,0.040000
|
||||||
|
2010-05-28,0.031000
|
||||||
|
2018-12-31,0.029000
|
||||||
|
2019-12-23,0.004000
|
||||||
|
2020-06-30,0.029000
|
||||||
|
2024-09-30,0.026000
|
||||||
|
2009-12-22,0.192000
|
||||||
|
2012-03-30,0.037000
|
||||||
|
2021-05-28,0.014000
|
||||||
|
2004-03-31,0.049000
|
||||||
|
2008-06-30,0.039000
|
||||||
|
2009-09-30,0.026000
|
||||||
|
2010-08-31,0.024000
|
||||||
|
2011-11-30,0.035000
|
||||||
|
2013-01-31,0.029000
|
||||||
|
2019-03-29,0.029000
|
||||||
|
2003-04-30,0.052000
|
||||||
|
2005-11-30,0.035000
|
||||||
|
2013-11-29,0.027000
|
||||||
|
2022-07-29,0.020000
|
||||||
|
2006-06-30,0.037000
|
||||||
|
2008-07-31,0.039000
|
||||||
|
2018-12-21,0.017000
|
||||||
|
2022-12-30,0.019000
|
||||||
|
2024-11-29,0.026000
|
||||||
|
2003-05-30,0.052000
|
||||||
|
2005-02-28,0.035000
|
||||||
|
2007-03-30,0.042000
|
||||||
|
2012-05-31,0.034000
|
||||||
|
2023-10-31,0.026000
|
||||||
|
2003-11-28,0.052000
|
||||||
|
2004-12-31,0.042000
|
||||||
|
2008-08-29,0.036000
|
||||||
|
2011-05-31,0.030000
|
||||||
|
2021-04-30,0.017000
|
||||||
|
2024-05-31,0.028000
|
||||||
|
2004-05-28,0.049000
|
||||||
|
2005-07-29,0.035000
|
||||||
|
2007-04-30,0.043000
|
||||||
|
2011-07-29,0.032000
|
||||||
|
2018-01-31,0.026000
|
||||||
|
2018-03-29,0.026000
|
||||||
|
2021-06-30,0.015000
|
||||||
|
2017-06-30,0.026000
|
||||||
|
2008-01-31,0.042000
|
||||||
|
2008-10-31,0.031000
|
||||||
|
2010-11-30,0.026000
|
||||||
|
2012-04-30,0.035000
|
||||||
|
2012-12-31,0.028000
|
||||||
|
2015-10-30,0.025000
|
||||||
|
2016-01-29,0.024000
|
||||||
|
2019-09-30,0.025000
|
||||||
|
2024-07-31,0.024000
|
||||||
|
2003-06-30,0.052000
|
||||||
|
2005-01-31,0.035000
|
||||||
|
2011-03-31,0.024000
|
||||||
|
2013-12-31,0.021000
|
||||||
|
2020-05-29,0.028000
|
||||||
|
2008-02-29,0.042000
|
||||||
|
2020-01-31,0.026000
|
||||||
|
2020-12-31,0.019000
|
||||||
|
2006-08-31,0.042000
|
||||||
|
2007-11-30,0.044000
|
||||||
|
2010-02-26,0.027000
|
||||||
|
2011-04-29,0.027000
|
||||||
|
2011-06-30,0.031000
|
||||||
|
2020-08-31,0.022000
|
||||||
|
2022-09-30,0.020000
|
||||||
|
2024-01-31,0.023000
|
||||||
|
2006-04-28,0.037000
|
||||||
|
2007-06-29,0.043000
|
||||||
|
2010-10-29,0.025000
|
||||||
|
2013-02-28,0.033000
|
||||||
|
2013-10-31,0.028000
|
||||||
|
2020-02-28,0.028000
|
||||||
|
2023-05-31,0.021000
|
||||||
|
2004-07-30,0.039000
|
||||||
|
2010-12-22,0.365000
|
||||||
|
2003-07-31,0.052000
|
||||||
|
2009-02-27,0.032000
|
||||||
|
2012-09-28,0.030000
|
||||||
|
2013-06-28,0.036000
|
||||||
|
2018-11-30,0.028000
|
||||||
|
2010-03-31,0.031000
|
||||||
|
2010-04-30,0.040000
|
||||||
|
2017-09-29,0.031000
|
||||||
|
2022-11-30,0.019000
|
||||||
|
2011-02-28,0.023000
|
||||||
|
2013-09-30,0.030000
|
||||||
|
2023-09-29,0.024000
|
||||||
|
2009-04-30,0.037000
|
||||||
|
2018-09-28,0.030000
|
||||||
|
2022-05-31,0.018000
|
||||||
|
2006-05-31,0.037000
|
||||||
|
2007-09-28,0.043000
|
||||||
|
2023-12-29,0.023000
|
||||||
|
2024-12-31,0.026000
|
||||||
|
2004-06-30,0.049000
|
||||||
|
2004-11-30,0.042000
|
||||||
|
2007-07-31,0.046000
|
||||||
|
2017-04-28,0.023000
|
||||||
|
2018-05-31,0.028000
|
||||||
|
2019-08-30,0.026000
|
||||||
|
2022-08-31,0.020000
|
||||||
|
2008-03-31,0.041000
|
||||||
|
2011-01-31,0.026000
|
||||||
|
2017-08-31,0.030000
|
||||||
|
2019-01-31,0.027000
|
||||||
|
2023-04-28,0.020000
|
||||||
|
2006-07-31,0.042000
|
||||||
|
2006-12-29,0.042000
|
||||||
|
2024-08-30,0.026000
|
||||||
|
2025-05-30,0.028000
|
||||||
|
2012-02-29,0.034000
|
||||||
|
2022-01-31,0.011000
|
||||||
|
2008-05-30,0.040000
|
||||||
|
2017-07-31,0.028000
|
||||||
|
2019-02-28,0.028000
|
||||||
|
2015-05-29,0.017000
|
||||||
|
2024-10-31,0.026000
|
||||||
|
2010-07-30,0.025000
|
||||||
|
2011-12-30,0.037000
|
||||||
|
2012-08-31,0.031000
|
||||||
|
2012-12-21,0.201000
|
||||||
|
2003-09-30,0.052000
|
||||||
|
2007-08-31,0.043000
|
||||||
|
2016-10-31,0.023000
|
||||||
|
2007-02-28,0.042000
|
||||||
|
2009-10-30,0.031000
|
||||||
|
2022-03-31,0.014000
|
||||||
|
2023-02-28,0.022000
|
||||||
|
2005-12-30,0.108000
|
||||||
|
2012-06-29,0.034000
|
||||||
|
2014-12-31,0.020000
|
||||||
|
2018-02-28,0.028000
|
||||||
|
2019-12-31,0.026000
|
||||||
|
2017-01-31,0.024000
|
||||||
|
2021-01-29,0.021000
|
||||||
|
2011-09-30,0.033000
|
||||||
|
2016-09-30,0.023000
|
||||||
|
2005-10-31,0.035000
|
||||||
|
2020-03-31,0.028000
|
||||||
|
2022-10-31,0.020000
|
||||||
|
2022-12-19,0.002000
|
||||||
|
2024-04-30,0.027000
|
||||||
|
2025-06-30,0.028000
|
||||||
|
2020-09-30,0.024000
|
||||||
|
2021-11-30,0.012000
|
||||||
|
2025-11-28,0.029000
|
||||||
|
2003-08-29,0.052000
|
||||||
|
2007-01-31,0.042000
|
||||||
|
2015-02-27,0.020000
|
||||||
|
2015-04-30,0.016000
|
||||||
|
2017-03-31,0.022000
|
||||||
|
2003-03-31,0.052000
|
||||||
|
2004-08-31,0.022000
|
||||||
|
2007-05-31,0.043000
|
||||||
|
2008-09-30,0.037000
|
||||||
|
2009-08-31,0.036000
|
||||||
|
2010-12-31,0.029000
|
||||||
|
2013-08-30,0.030000
|
||||||
|
2017-05-31,0.025000
|
||||||
|
2006-02-28,0.038000
|
||||||
|
2014-01-31,0.021000
|
||||||
|
2019-05-31,0.029000
|
||||||
|
2020-04-30,0.030000
|
||||||
|
2003-12-31,0.052000
|
||||||
|
2014-03-31,0.018000
|
||||||
|
2023-11-30,0.023000
|
||||||
|
2009-01-30,0.031000
|
||||||
|
2016-07-29,0.024000
|
||||||
|
2004-09-30,0.022000
|
||||||
|
2006-09-29,0.042000
|
||||||
|
2009-05-29,0.040000
|
||||||
|
2010-01-29,0.027000
|
||||||
|
2010-06-30,0.026000
|
||||||
|
2010-09-30,0.025000
|
||||||
|
2015-09-30,0.027000
|
||||||
|
2014-04-30,0.019000
|
||||||
|
2014-11-28,0.021000
|
||||||
|
2016-03-31,0.024000
|
||||||
|
2016-11-30,0.024000
|
||||||
|
2020-11-30,0.022000
|
||||||
|
2025-08-29,0.028000
|
||||||
|
2022-02-28,0.012000
|
||||||
|
2023-08-31,0.025000
|
||||||
|
2025-01-31,0.027000
|
||||||
|
2014-09-30,0.023000
|
||||||
|
2015-03-31,0.018000
|
||||||
|
2016-12-30,0.024000
|
||||||
|
2025-04-30,0.027000
|
||||||
|
2003-02-28,0.052000
|
||||||
|
2016-05-31,0.023000
|
||||||
|
2019-11-29,0.026000
|
||||||
|
2025-07-31,0.028000
|
||||||
|
2005-04-29,0.035000
|
||||||
|
2009-03-31,0.035000
|
||||||
|
2018-04-30,0.027000
|
||||||
|
2022-06-30,0.021000
|
||||||
|
2024-02-29,0.023000
|
||||||
|
2005-06-30,0.035000
|
||||||
|
2008-04-30,0.041000
|
||||||
|
2012-01-31,0.037000
|
||||||
|
2015-11-30,0.025000
|
||||||
|
2018-07-31,0.028000
|
||||||
|
2021-09-30,0.015000
|
||||||
|
2023-03-31,0.021000
|
||||||
|
2009-07-31,0.039000
|
||||||
|
2004-01-30,0.052000
|
||||||
|
2016-08-31,0.023000
|
||||||
|
2019-07-31,0.027000
|
||||||
|
2025-02-28,0.027000
|
||||||
|
2023-06-30,0.021000
|
||||||
|
2004-02-27,0.052000
|
||||||
|
2004-04-30,0.049000
|
||||||
|
2012-11-30,0.029000
|
||||||
|
2014-05-30,0.019000
|
||||||
|
2018-06-29,0.028000
|
||||||
|
2018-10-31,0.029000
|
||||||
|
2022-04-29,0.016000
|
||||||
|
2012-10-31,0.030000
|
||||||
|
2014-06-30,0.019000
|
||||||
|
2015-12-31,0.025000
|
||||||
|
2005-08-31,0.035000
|
||||||
|
2009-11-30,0.026000
|
||||||
|
2019-06-28,0.027000
|
||||||
|
2005-03-31,0.035000
|
||||||
|
2017-12-22,0.004000
|
||||||
|
2021-10-29,0.014000
|
||||||
|
2006-10-31,0.042000
|
||||||
|
2017-12-29,0.027000
|
||||||
|
5792
overrides/frozen/bbgpx-history.csv
Normal file
5792
overrides/frozen/bbgpx-history.csv
Normal file
File diff suppressed because it is too large
Load Diff
7
overrides/frozen/bbgpx.json
Normal file
7
overrides/frozen/bbgpx.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"symbol": "bbgpx",
|
||||||
|
"longName": "BlackRock ETF Trust II - iShares Mortgage-Backed Securities Active ETF",
|
||||||
|
"freeze_date": "2025-12-26",
|
||||||
|
"created": "2026-08-31",
|
||||||
|
"reason": "yahoo-empty"
|
||||||
|
}
|
||||||
11
overrides/frozen/bcmix-capitalGain.csv
Normal file
11
overrides/frozen/bcmix-capitalGain.csv
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
Date,Capital Gains
|
||||||
|
2012-12-14,0.354000
|
||||||
|
2016-12-13,0.611000
|
||||||
|
2019-12-12,0.613000
|
||||||
|
2020-12-11,0.453000
|
||||||
|
2022-12-12,1.859000
|
||||||
|
2014-12-12,1.809000
|
||||||
|
2015-12-11,11.223000
|
||||||
|
2017-12-12,2.419000
|
||||||
|
2018-12-12,1.137000
|
||||||
|
2021-12-10,0.500000
|
||||||
|
11
overrides/frozen/bcmix-dividend.csv
Normal file
11
overrides/frozen/bcmix-dividend.csv
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
Date,Dividends
|
||||||
|
2019-12-12,0.613000
|
||||||
|
2021-12-10,0.500000
|
||||||
|
2022-12-12,1.859000
|
||||||
|
2012-12-14,0.354000
|
||||||
|
2014-12-12,1.809000
|
||||||
|
2015-12-11,11.223000
|
||||||
|
2016-12-13,0.611000
|
||||||
|
2017-12-12,2.419000
|
||||||
|
2018-12-12,1.137000
|
||||||
|
2020-12-11,0.453000
|
||||||
|
3269
overrides/frozen/bcmix-history.csv
Normal file
3269
overrides/frozen/bcmix-history.csv
Normal file
File diff suppressed because it is too large
Load Diff
7
overrides/frozen/bcmix.json
Normal file
7
overrides/frozen/bcmix.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"symbol": "bcmix",
|
||||||
|
"longName": "Brown Capital Management Mutual Funds - The Brown Capital Management Mid Company Fund",
|
||||||
|
"freeze_date": "2024-12-11",
|
||||||
|
"created": "2026-08-31",
|
||||||
|
"reason": "yahoo-empty"
|
||||||
|
}
|
||||||
2
overrides/frozen/bfslx-dividend.csv
Normal file
2
overrides/frozen/bfslx-dividend.csv
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
Date,Dividends,ctime
|
||||||
|
2014-12-02,0.191,2017-08-22
|
||||||
|
2712
overrides/frozen/bfslx-history.csv
Normal file
2712
overrides/frozen/bfslx-history.csv
Normal file
File diff suppressed because it is too large
Load Diff
7
overrides/frozen/bfslx.json
Normal file
7
overrides/frozen/bfslx.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"symbol": "bfslx",
|
||||||
|
"longName": "?",
|
||||||
|
"freeze_date": "2018-03-16",
|
||||||
|
"created": "2026-08-31",
|
||||||
|
"reason": "yahoo-empty"
|
||||||
|
}
|
||||||
4
overrides/frozen/bgaqx-dividend.csv
Normal file
4
overrides/frozen/bgaqx-dividend.csv
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
Date,Dividends
|
||||||
|
2017-12-06,0.007000
|
||||||
|
2018-12-06,0.114000
|
||||||
|
2019-12-04,0.724000
|
||||||
|
19
overrides/frozen/bgaqx-history.csv
Normal file
19
overrides/frozen/bgaqx-history.csv
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
Date,Open,High,Low,Close,Adj Close,Volume
|
||||||
|
2020-03-05,0.100000,0.100000,0.100000,0.100000,0.100000,0
|
||||||
|
2020-03-06,0.100000,0.100000,0.100000,0.100000,0.100000,0
|
||||||
|
2020-03-09,0.100000,0.100000,0.100000,0.100000,0.100000,0
|
||||||
|
2020-03-10,0.100000,0.100000,0.100000,0.100000,0.100000,0
|
||||||
|
2020-03-11,0.100000,0.100000,0.100000,0.100000,0.100000,0
|
||||||
|
2020-03-12,0.100000,0.100000,0.100000,0.100000,0.100000,0
|
||||||
|
2020-03-13,0.100000,0.100000,0.100000,0.100000,0.100000,0
|
||||||
|
2020-03-16,0.100000,0.100000,0.100000,0.100000,0.100000,0
|
||||||
|
2020-03-17,0.100000,0.100000,0.100000,0.100000,0.100000,0
|
||||||
|
2020-03-18,0.100000,0.100000,0.100000,0.100000,0.100000,0
|
||||||
|
2020-03-19,0.100000,0.100000,0.100000,0.100000,0.100000,0
|
||||||
|
2020-03-20,0.100000,0.100000,0.100000,0.100000,0.100000,0
|
||||||
|
2020-03-23,0.100000,0.100000,0.100000,0.100000,0.100000,0
|
||||||
|
2020-03-24,0.100000,0.100000,0.100000,0.100000,0.100000,0
|
||||||
|
2020-03-25,0.100000,0.100000,0.100000,0.100000,0.100000,0
|
||||||
|
2020-03-26,0.100000,0.100000,0.100000,0.100000,0.100000,0
|
||||||
|
2020-03-27,0.100000,0.100000,0.100000,0.100000,0.100000,0
|
||||||
|
2020-03-30,0.100000,0.100000,0.100000,0.100000,0.100000,0
|
||||||
|
7
overrides/frozen/bgaqx.json
Normal file
7
overrides/frozen/bgaqx.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"symbol": "bgaqx",
|
||||||
|
"longName": "BMO Global Long/Short Equity Fund Class A",
|
||||||
|
"freeze_date": "2020-03-30",
|
||||||
|
"created": "2026-08-31",
|
||||||
|
"reason": "yahoo-empty"
|
||||||
|
}
|
||||||
4
overrides/frozen/bgrsx-capitalGain.csv
Normal file
4
overrides/frozen/bgrsx-capitalGain.csv
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
Date,Capital Gains
|
||||||
|
2018-12-13,0.203000
|
||||||
|
2024-09-19,1.467000
|
||||||
|
2015-12-17,0.044000
|
||||||
|
8
overrides/frozen/bgrsx-dividend.csv
Normal file
8
overrides/frozen/bgrsx-dividend.csv
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
Date,Dividends
|
||||||
|
2016-12-15,0.015000
|
||||||
|
2018-12-13,0.203000
|
||||||
|
2019-12-12,0.104000
|
||||||
|
2022-12-08,0.304000
|
||||||
|
2023-12-14,0.201000
|
||||||
|
2024-09-19,1.592000
|
||||||
|
2015-12-17,0.044000
|
||||||
|
2698
overrides/frozen/bgrsx-history.csv
Normal file
2698
overrides/frozen/bgrsx-history.csv
Normal file
File diff suppressed because it is too large
Load Diff
7
overrides/frozen/bgrsx.json
Normal file
7
overrides/frozen/bgrsx.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"symbol": "bgrsx",
|
||||||
|
"longName": "The RBB Fund, Inc. - Boston Partners Global Long/Short Fund",
|
||||||
|
"freeze_date": "2024-12-30",
|
||||||
|
"created": "2026-08-31",
|
||||||
|
"reason": "yahoo-empty"
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user