60 行
2.5 KiB
Python
60 行
2.5 KiB
Python
"""
| |||
M1 (FX_PLAN.md): month-end USD flow.
| |||
| |||
Two fixed windows, no parameters:
| |||
END : enter at the close of the 3rd-last trading day, exit at the close of
| |||
the last trading day of the month (the last 2 days)
| |||
START : enter at the close of the last trading day, exit at the close of the
| |||
2nd trading day of the new month (the first 2 days)
| |||
Returns are expressed as USD direction (+ = USD strengthened) so all USD pairs
| |||
can be pooled; the side is the IS sign, fixed before OOS is looked at.
| |||
"""
| |||
| |||
from __future__ import annotations
| |||
| |||
import sys
| |||
import numpy as np
| |||
| |||
sys.path.insert(0, __file__.rsplit("\\", 1)[0] if "\\" in __file__ else ".")
| |||
import fx_screen as fs # noqa: E402
| |||
| |||
USD = {"EURUSD": -1, "GBPUSD": -1, "AUDUSD": -1, "NZDUSD": -1,
| |||
"USDJPY": 1, "USDCHF": 1, "USDCAD": 1, "XAUUSD": -1}
| |||
| |||
| |||
def windows(d):
| |||
ts = d["ts"].astype("datetime64[D]")
| |||
mon = ts.astype("datetime64[M]")
| |||
c, cost = d["c"], d["cost"]
| |||
end_r, start_r, t_end = [], [], []
| |||
last = np.where(mon[1:] != mon[:-1])[0] # index of last bar of each month
| |||
for i in last:
| |||
if i - 2 < 0 or i + 2 >= len(c):
| |||
continue
| |||
end_r.append(((c[i] - c[i - 2]) - cost[i - 2]) / c[i - 2] if False else (c[i] - c[i - 2]) / c[i - 2])
| |||
start_r.append((c[i + 2] - c[i]) / c[i])
| |||
t_end.append(ts[i])
| |||
return np.array(t_end), np.array(end_r), np.array(start_r), cost, c
| |||
| |||
| |||
if __name__ == "__main__":
| |||
split = np.datetime64("2016-01-01")
| |||
pooled = {"END": ([], []), "START": ([], [])}
| |||
print(f"{'sym':<8}{'win':>6}{'IS bp(USD+)':>12}{'IS t':>7}{'OOS bp':>9}{'OOS t':>7}")
| |||
for s, usd in USD.items():
| |||
d = fs.load(s, "D1")
| |||
t, er, sr, cost, c = windows(d)
| |||
spread = np.median(cost / c)
| |||
for nm, r in (("END", er), ("START", sr)):
| |||
usd_r = usd * r
| |||
is_, oos = usd_r[t < split], usd_r[t >= split]
| |||
pooled[nm][0].extend(is_)
| |||
pooled[nm][1].extend(oos)
| |||
print(f"{s:<8}{nm:>6}{is_.mean() * 1e4:>12.1f}{fs.tstat(is_):>7.2f}{oos.mean() * 1e4:>9.1f}"
| |||
f"{fs.tstat(oos):>7.2f} (spread {spread * 1e4:.1f} bp)")
| |||
print()
| |||
for nm, (a, b) in pooled.items():
| |||
side = np.sign(np.mean(a))
| |||
print(f"POOLED {nm}: IS {np.mean(a) * 1e4:+.1f} bp USD (t {fs.tstat(a):.2f}) -> trade side "
| |||
f"{'long USD' if side > 0 else 'short USD'}; OOS in that direction {side * np.mean(b) * 1e4:+.1f} bp "
| |||
f"(t {fs.tstat(side * np.array(b)):.2f}, n {len(b)})")
|