lit-forge-mcp 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -4
- package/dist/index.js +1 -1
- package/dist/lib/__tests__/correlation.test.d.ts +1 -0
- package/dist/lib/__tests__/correlation.test.js +53 -0
- package/dist/lib/__tests__/correlation.test.js.map +1 -0
- package/dist/lib/__tests__/quartile.test.d.ts +1 -0
- package/dist/lib/__tests__/quartile.test.js +148 -0
- package/dist/lib/__tests__/quartile.test.js.map +1 -0
- package/dist/lib/__tests__/rankings.test.d.ts +1 -0
- package/dist/lib/__tests__/rankings.test.js +67 -0
- package/dist/lib/__tests__/rankings.test.js.map +1 -0
- package/dist/lib/__tests__/sessions.test.d.ts +1 -0
- package/dist/lib/__tests__/sessions.test.js +47 -0
- package/dist/lib/__tests__/sessions.test.js.map +1 -0
- package/dist/lib/__tests__/sma.test.d.ts +1 -0
- package/dist/lib/__tests__/sma.test.js +26 -0
- package/dist/lib/__tests__/sma.test.js.map +1 -0
- package/dist/lib/__tests__/thermometer.test.d.ts +1 -0
- package/dist/lib/__tests__/thermometer.test.js +120 -0
- package/dist/lib/__tests__/thermometer.test.js.map +1 -0
- package/dist/lib/__tests__/yield-spread.test.d.ts +1 -0
- package/dist/lib/__tests__/yield-spread.test.js +46 -0
- package/dist/lib/__tests__/yield-spread.test.js.map +1 -0
- package/dist/lib/correlation.d.ts +3 -0
- package/dist/lib/correlation.js +77 -0
- package/dist/lib/correlation.js.map +1 -0
- package/dist/lib/economic-events.d.ts +9 -0
- package/dist/lib/economic-events.js +146 -0
- package/dist/lib/economic-events.js.map +1 -0
- package/dist/lib/fangplus.d.ts +7 -0
- package/dist/lib/fangplus.js +19 -0
- package/dist/lib/fangplus.js.map +1 -0
- package/dist/lib/indicators.d.ts +3 -0
- package/dist/lib/indicators.js +49 -0
- package/dist/lib/indicators.js.map +1 -0
- package/dist/lib/mag7.d.ts +7 -0
- package/dist/lib/mag7.js +13 -0
- package/dist/lib/mag7.js.map +1 -0
- package/dist/lib/market-types.d.ts +57 -0
- package/dist/lib/market-types.js +5 -0
- package/dist/lib/market-types.js.map +1 -0
- package/dist/lib/performance.d.ts +3 -0
- package/dist/lib/performance.js +43 -0
- package/dist/lib/performance.js.map +1 -0
- package/dist/lib/quartile.d.ts +24 -0
- package/dist/lib/quartile.js +128 -0
- package/dist/lib/quartile.js.map +1 -0
- package/dist/lib/rankings.d.ts +7 -0
- package/dist/lib/rankings.js +29 -0
- package/dist/lib/rankings.js.map +1 -0
- package/dist/lib/sectors.d.ts +7 -0
- package/dist/lib/sectors.js +62 -0
- package/dist/lib/sectors.js.map +1 -0
- package/dist/lib/sessions.d.ts +14 -0
- package/dist/lib/sessions.js +50 -0
- package/dist/lib/sessions.js.map +1 -0
- package/dist/lib/sma.d.ts +2 -0
- package/dist/lib/sma.js +33 -0
- package/dist/lib/sma.js.map +1 -0
- package/dist/lib/thermometer.d.ts +13 -0
- package/dist/lib/thermometer.js +118 -0
- package/dist/lib/thermometer.js.map +1 -0
- package/dist/lib/yahoo.d.ts +11 -0
- package/dist/lib/yahoo.js +171 -0
- package/dist/lib/yahoo.js.map +1 -0
- package/dist/lib/yield-spread.d.ts +6 -0
- package/dist/lib/yield-spread.js +20 -0
- package/dist/lib/yield-spread.js.map +1 -0
- package/dist/tools/get-economic-events.d.ts +2 -0
- package/dist/tools/get-economic-events.js +42 -0
- package/dist/tools/get-economic-events.js.map +1 -0
- package/dist/tools/get-market-sessions.d.ts +2 -0
- package/dist/tools/get-market-sessions.js +27 -0
- package/dist/tools/get-market-sessions.js.map +1 -0
- package/dist/tools/get-market-snapshot.d.ts +2 -0
- package/dist/tools/get-market-snapshot.js +29 -0
- package/dist/tools/get-market-snapshot.js.map +1 -0
- package/dist/tools/get-market-thermometer.d.ts +2 -0
- package/dist/tools/get-market-thermometer.js +47 -0
- package/dist/tools/get-market-thermometer.js.map +1 -0
- package/dist/tools/get-performance-ranking.d.ts +2 -0
- package/dist/tools/get-performance-ranking.js +75 -0
- package/dist/tools/get-performance-ranking.js.map +1 -0
- package/dist/tools/get-quote.d.ts +2 -0
- package/dist/tools/get-quote.js +31 -0
- package/dist/tools/get-quote.js.map +1 -0
- package/dist/tools/get-sector-heatmap.d.ts +2 -0
- package/dist/tools/get-sector-heatmap.js +34 -0
- package/dist/tools/get-sector-heatmap.js.map +1 -0
- package/dist/tools/get-yield-spread.d.ts +2 -0
- package/dist/tools/get-yield-spread.js +41 -0
- package/dist/tools/get-yield-spread.js.map +1 -0
- package/dist/tools/index.js +21 -0
- package/dist/tools/index.js.map +1 -1
- package/package.json +10 -3
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// 過去 1 年(≒ 252 営業日)の close 配列に対する現在値の分位値(パーセンタイル)を計算。
|
|
2
|
+
// 「現在値が過去 1 年で X% の位置(0=最安、100=最高)」を返す。
|
|
3
|
+
// /today の MarketCard 上で「過去1年で上位X%」のようなヒストリカル文脈表示に使う。
|
|
4
|
+
const MIN_POINTS = 30; // この点数未満は分位値を算出しない(信頼性低)
|
|
5
|
+
// closes に対する現在値(= 末尾要素)のパーセンタイル順位(0..100)。
|
|
6
|
+
// データ点不足は null。
|
|
7
|
+
export function pricePercentile(closes) {
|
|
8
|
+
if (closes.length < MIN_POINTS)
|
|
9
|
+
return null;
|
|
10
|
+
const current = closes[closes.length - 1];
|
|
11
|
+
if (typeof current !== "number" || Number.isNaN(current))
|
|
12
|
+
return null;
|
|
13
|
+
// 末尾要素を除いた過去履歴に対してランクを取る(自己一致を除外)
|
|
14
|
+
const past = closes.slice(0, -1);
|
|
15
|
+
const lessOrEq = past.filter((v) => v <= current).length;
|
|
16
|
+
return (lessOrEq / past.length) * 100;
|
|
17
|
+
}
|
|
18
|
+
export function detectOutlier(closes, todayChangePercent) {
|
|
19
|
+
if (closes.length < MIN_POINTS)
|
|
20
|
+
return null;
|
|
21
|
+
// 各営業日変化率の系列を作る
|
|
22
|
+
const returns = [];
|
|
23
|
+
for (let i = 1; i < closes.length; i++) {
|
|
24
|
+
const prev = closes[i - 1];
|
|
25
|
+
const curr = closes[i];
|
|
26
|
+
if (prev === 0 || typeof prev !== "number" || typeof curr !== "number")
|
|
27
|
+
continue;
|
|
28
|
+
returns.push(((curr - prev) / prev) * 100);
|
|
29
|
+
}
|
|
30
|
+
if (returns.length < MIN_POINTS)
|
|
31
|
+
return null;
|
|
32
|
+
const mean = returns.reduce((a, b) => a + b, 0) / returns.length;
|
|
33
|
+
const variance = returns.reduce((sum, r) => sum + (r - mean) ** 2, 0) / returns.length;
|
|
34
|
+
const std = Math.sqrt(variance);
|
|
35
|
+
if (std === 0)
|
|
36
|
+
return null;
|
|
37
|
+
const sigma = (todayChangePercent - mean) / std;
|
|
38
|
+
return { sigma, exceeds1Sigma: Math.abs(sigma) >= 1 };
|
|
39
|
+
}
|
|
40
|
+
const MA200_LEN = 200;
|
|
41
|
+
function sma(values) {
|
|
42
|
+
if (values.length === 0)
|
|
43
|
+
return null;
|
|
44
|
+
return values.reduce((a, b) => a + b, 0) / values.length;
|
|
45
|
+
}
|
|
46
|
+
// closes1y / dayHigh / dayLow / fiftyTwoWeekHigh / fiftyTwoWeekLow から重要レベルイベントを抽出。
|
|
47
|
+
// データ不足時は空配列。複数同時起きる場合は配列で全部返す(呼び出し側で先頭 N 件を表示)。
|
|
48
|
+
export function detectLevelEvents(input) {
|
|
49
|
+
const out = [];
|
|
50
|
+
// 52 週新高値・新安値:当日高値が 52w 高値以上 / 当日安値が 52w 安値以下
|
|
51
|
+
if (typeof input.dayHigh === "number" &&
|
|
52
|
+
typeof input.fiftyTwoWeekHigh === "number" &&
|
|
53
|
+
input.dayHigh >= input.fiftyTwoWeekHigh) {
|
|
54
|
+
out.push({ type: "52w-new-high", label: "🏔️ 52週新高値" });
|
|
55
|
+
}
|
|
56
|
+
if (typeof input.dayLow === "number" &&
|
|
57
|
+
typeof input.fiftyTwoWeekLow === "number" &&
|
|
58
|
+
input.dayLow <= input.fiftyTwoWeekLow &&
|
|
59
|
+
input.fiftyTwoWeekLow > 0) {
|
|
60
|
+
out.push({ type: "52w-new-low", label: "📉 52週新安値" });
|
|
61
|
+
}
|
|
62
|
+
// 200 日線クロス:直近の close と前日 close を 200 日 SMA と比較。
|
|
63
|
+
const closes = input.closes1y;
|
|
64
|
+
if (closes && closes.length >= MA200_LEN + 1) {
|
|
65
|
+
const last = closes[closes.length - 1];
|
|
66
|
+
const prev = closes[closes.length - 2];
|
|
67
|
+
const lastSma = sma(closes.slice(-MA200_LEN));
|
|
68
|
+
const prevSma = sma(closes.slice(-MA200_LEN - 1, -1));
|
|
69
|
+
if (typeof last === "number" &&
|
|
70
|
+
typeof prev === "number" &&
|
|
71
|
+
lastSma !== null &&
|
|
72
|
+
prevSma !== null) {
|
|
73
|
+
if (last > lastSma && prev <= prevSma) {
|
|
74
|
+
out.push({ type: "ma200-cross-up", label: "📈 200日線上抜け" });
|
|
75
|
+
}
|
|
76
|
+
else if (last < lastSma && prev >= prevSma) {
|
|
77
|
+
out.push({ type: "ma200-cross-down", label: "📉 200日線下抜け" });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return out;
|
|
82
|
+
}
|
|
83
|
+
const MILESTONE_BUCKETS = [252, 90, 60, 30];
|
|
84
|
+
export function detectMilestone(closes) {
|
|
85
|
+
if (closes.length < 31)
|
|
86
|
+
return null;
|
|
87
|
+
const last = closes[closes.length - 1];
|
|
88
|
+
if (typeof last !== "number")
|
|
89
|
+
return null;
|
|
90
|
+
for (const days of MILESTONE_BUCKETS) {
|
|
91
|
+
if (closes.length <= days)
|
|
92
|
+
continue;
|
|
93
|
+
const window = closes.slice(-days - 1, -1); // 直前 N 日(自身を除く)
|
|
94
|
+
const max = Math.max(...window);
|
|
95
|
+
const min = Math.min(...window);
|
|
96
|
+
if (last > max) {
|
|
97
|
+
return {
|
|
98
|
+
type: "n-day-high",
|
|
99
|
+
days,
|
|
100
|
+
label: days >= 252 ? "📅 1年ぶり高値" : `📅 ${days}日ぶり高値`,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
if (last < min) {
|
|
104
|
+
return {
|
|
105
|
+
type: "n-day-low",
|
|
106
|
+
days,
|
|
107
|
+
label: days >= 252 ? "📅 1年ぶり安値" : `📅 ${days}日ぶり安値`,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
// パーセンタイル値を「上位/下位/中央寄り」の短文ラベルに変換。
|
|
114
|
+
// percentile null → 空文字(呼び出し側で非表示)。
|
|
115
|
+
export function percentileLabel(percentile) {
|
|
116
|
+
if (percentile === null)
|
|
117
|
+
return "";
|
|
118
|
+
if (percentile >= 90)
|
|
119
|
+
return `過去1年で上位${(100 - percentile).toFixed(0)}%水準`;
|
|
120
|
+
if (percentile >= 70)
|
|
121
|
+
return `過去1年で上位${(100 - percentile).toFixed(0)}%`;
|
|
122
|
+
if (percentile >= 30)
|
|
123
|
+
return `過去1年で中央値付近`;
|
|
124
|
+
if (percentile >= 10)
|
|
125
|
+
return `過去1年で下位${percentile.toFixed(0)}%`;
|
|
126
|
+
return `過去1年で下位${percentile.toFixed(0)}%水準`;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=quartile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quartile.js","sourceRoot":"","sources":["../../src/lib/quartile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Indicator, QuoteResult } from "./market-types.js";
|
|
2
|
+
export type RankingPeriod = "1d" | "1w" | "1m";
|
|
3
|
+
export type RankedItem = {
|
|
4
|
+
indicator: Indicator;
|
|
5
|
+
pct: number;
|
|
6
|
+
};
|
|
7
|
+
export declare function rankByPerformance(indicators: readonly Indicator[], quotes: Record<string, QuoteResult>, period: RankingPeriod): RankedItem[];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// 27 銘柄を期間別パフォーマンスでソートするランキング純関数。
|
|
2
|
+
// /today の PerformanceRanking で「上位 N / 下位 N」を表示するために使う。
|
|
3
|
+
//
|
|
4
|
+
// 期間:1d は changePercent、1w/1m は performance.d7 / d30 を使用。
|
|
5
|
+
// performance フィールドが無い銘柄は除外。
|
|
6
|
+
function getPctForPeriod(quote, period) {
|
|
7
|
+
if (period === "1d")
|
|
8
|
+
return quote.changePercent;
|
|
9
|
+
if (period === "1w")
|
|
10
|
+
return quote.performance?.d7 ?? null;
|
|
11
|
+
return quote.performance?.d30 ?? null;
|
|
12
|
+
}
|
|
13
|
+
// 全 INDICATORS から、指定期間のパフォーマンス降順で並べ替えた配列を返す。
|
|
14
|
+
// データ無し銘柄は除外。
|
|
15
|
+
export function rankByPerformance(indicators, quotes, period) {
|
|
16
|
+
const items = [];
|
|
17
|
+
for (const ind of indicators) {
|
|
18
|
+
const q = quotes[ind.symbol];
|
|
19
|
+
if (!q || "error" in q)
|
|
20
|
+
continue;
|
|
21
|
+
const pct = getPctForPeriod(q, period);
|
|
22
|
+
if (pct === null || Number.isNaN(pct))
|
|
23
|
+
continue;
|
|
24
|
+
items.push({ indicator: ind, pct });
|
|
25
|
+
}
|
|
26
|
+
items.sort((a, b) => b.pct - a.pct);
|
|
27
|
+
return items;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=rankings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rankings.js","sourceRoot":"","sources":["../../src/lib/rankings.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAClC,wDAAwD;AACxD,EAAE;AACF,0DAA0D;AAC1D,6BAA6B;AAW7B,SAAS,eAAe,CAAC,KAAY,EAAE,MAAqB;IAC1D,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC,aAAa,CAAC;IAChD,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC,WAAW,EAAE,EAAE,IAAI,IAAI,CAAC;IAC1D,OAAO,KAAK,CAAC,WAAW,EAAE,GAAG,IAAI,IAAI,CAAC;AACxC,CAAC;AAED,6CAA6C;AAC7C,cAAc;AACd,MAAM,UAAU,iBAAiB,CAC/B,UAAgC,EAChC,MAAmC,EACnC,MAAqB;IAErB,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC7B,IAAI,CAAC,CAAC,IAAI,OAAO,IAAI,CAAC;YAAE,SAAS;QACjC,MAAM,GAAG,GAAG,eAAe,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACvC,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC;YAAE,SAAS;QAChD,KAAK,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IACtC,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACpC,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// 米株セクター ETF(State Street Sector SPDR、11 銘柄)。
|
|
2
|
+
// 各セクターの前日比をコンパクトなヒートマップで表示し、米株市場の解像度を上げる。
|
|
3
|
+
// /today では INDICATORS(27 銘柄)と並行して別セクションで取得・表示する。
|
|
4
|
+
export const SECTOR_ETFS = [
|
|
5
|
+
{
|
|
6
|
+
symbol: "XLK",
|
|
7
|
+
name: "テクノロジー",
|
|
8
|
+
description: "Apple / Microsoft / Nvidia など。AI・半導体・SaaS",
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
symbol: "XLF",
|
|
12
|
+
name: "金融",
|
|
13
|
+
description: "JPMorgan / Bank of America など。銀行・保険・証券",
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
symbol: "XLV",
|
|
17
|
+
name: "ヘルスケア",
|
|
18
|
+
description: "UnitedHealth / J&J / Eli Lilly など。製薬・医療機器",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
symbol: "XLY",
|
|
22
|
+
name: "一般消費財",
|
|
23
|
+
description: "Amazon / Tesla / McDonald's など。景気敏感セクター",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
symbol: "XLP",
|
|
27
|
+
name: "生活必需品",
|
|
28
|
+
description: "P&G / Coca-Cola / Walmart など。ディフェンシブ",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
symbol: "XLE",
|
|
32
|
+
name: "エネルギー",
|
|
33
|
+
description: "ExxonMobil / Chevron など。原油価格と連動",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
symbol: "XLI",
|
|
37
|
+
name: "資本財",
|
|
38
|
+
description: "Boeing / Caterpillar / GE など。製造業・防衛",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
symbol: "XLU",
|
|
42
|
+
name: "公益",
|
|
43
|
+
description: "電力・ガス・水道。低 β のディフェンシブ",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
symbol: "XLB",
|
|
47
|
+
name: "素材",
|
|
48
|
+
description: "化学・鉱業・金属。Linde / Sherwin-Williams など",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
symbol: "XLRE",
|
|
52
|
+
name: "不動産",
|
|
53
|
+
description: "REIT 中心。金利感応度が高い",
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
symbol: "XLC",
|
|
57
|
+
name: "通信",
|
|
58
|
+
description: "Meta / Alphabet / Netflix など。メディア・通信",
|
|
59
|
+
},
|
|
60
|
+
];
|
|
61
|
+
export const SECTOR_SYMBOLS = SECTOR_ETFS.map((s) => s.symbol);
|
|
62
|
+
//# sourceMappingURL=sectors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sectors.js","sourceRoot":"","sources":["../../src/lib/sectors.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,2CAA2C;AAC3C,kDAAkD;AAUlD,MAAM,CAAC,MAAM,WAAW,GAAyB;IAC/C;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,2CAA2C;KACzD;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,IAAI;QACV,WAAW,EAAE,wCAAwC;KACtD;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,2CAA2C;KACzD;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,yCAAyC;KACvD;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,sCAAsC;KACpD;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,iCAAiC;KAC/C;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,KAAK;QACX,WAAW,EAAE,qCAAqC;KACnD;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,IAAI;QACV,WAAW,EAAE,uBAAuB;KACrC;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,IAAI;QACV,WAAW,EAAE,sCAAsC;KACpD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,KAAK;QACX,WAAW,EAAE,kBAAkB;KAChC;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,IAAI;QACV,WAAW,EAAE,sCAAsC;KACpD;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAsB,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type MarketSession = {
|
|
2
|
+
id: "tokyo" | "london" | "ny" | "shanghai";
|
|
3
|
+
label: string;
|
|
4
|
+
openHourJst: number;
|
|
5
|
+
closeHourJst: number;
|
|
6
|
+
};
|
|
7
|
+
export declare const MARKET_SESSIONS: readonly MarketSession[];
|
|
8
|
+
export type SessionStatus = {
|
|
9
|
+
session: MarketSession;
|
|
10
|
+
state: "open" | "closed" | "pre-open";
|
|
11
|
+
hoursUntilOpen?: number;
|
|
12
|
+
hoursUntilClose?: number;
|
|
13
|
+
};
|
|
14
|
+
export declare function getSessionStatuses(now?: Date): SessionStatus[];
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// 主要市場の取引時間帯を JST 基準で判定する純関数。
|
|
2
|
+
// 東京・ロンドン・ニューヨーク・上海の取引時間を JST 換算してオープン/クローズ判定する。
|
|
3
|
+
// 祝日や臨時休場までは追わない(運営許容範囲)。
|
|
4
|
+
// 通常取引時間(JST、サマータイム未考慮)。
|
|
5
|
+
// 東京: 9:00-15:30 JST
|
|
6
|
+
// 上海: 10:30-16:00 JST
|
|
7
|
+
// ロンドン: 17:00-25:30 JST(17:00-翌1:30)— UTC 8:00-16:30
|
|
8
|
+
// NY: 22:30-29:00 JST(22:30-翌5:00)— UTC 13:30-20:00
|
|
9
|
+
export const MARKET_SESSIONS = [
|
|
10
|
+
{ id: "tokyo", label: "東京", openHourJst: 9, closeHourJst: 15.5 },
|
|
11
|
+
{ id: "shanghai", label: "上海", openHourJst: 10.5, closeHourJst: 16 },
|
|
12
|
+
{ id: "london", label: "ロンドン", openHourJst: 17, closeHourJst: 25.5 },
|
|
13
|
+
{ id: "ny", label: "NY", openHourJst: 22.5, closeHourJst: 29 },
|
|
14
|
+
];
|
|
15
|
+
// JST 時刻(now)から各市場のステータスを判定。
|
|
16
|
+
// open: 取引中、pre-open: 30 分以内にオープン、closed: それ以外。
|
|
17
|
+
export function getSessionStatuses(now = new Date()) {
|
|
18
|
+
const jstMs = now.getTime() + 9 * 3600 * 1000;
|
|
19
|
+
const jst = new Date(jstMs);
|
|
20
|
+
const dayOfWeek = jst.getUTCDay(); // 0=日, 6=土(JST 換算で)
|
|
21
|
+
const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;
|
|
22
|
+
// 現在時刻を「24h 換算の小数」で表現(例: 22:30 → 22.5)。
|
|
23
|
+
// 翌日にまたがるセッションは現在時刻 + 24 とも比較できるよう dual で持つ。
|
|
24
|
+
const hour = jst.getUTCHours() + jst.getUTCMinutes() / 60;
|
|
25
|
+
return MARKET_SESSIONS.map((s) => {
|
|
26
|
+
if (isWeekend) {
|
|
27
|
+
// 週末は基本クローズ(厳密には金曜深夜の NY セッション越境はあるが省略)
|
|
28
|
+
return { session: s, state: "closed" };
|
|
29
|
+
}
|
|
30
|
+
// 取引時間判定(hour と hour+24 の両方をチェック)
|
|
31
|
+
let state = "closed";
|
|
32
|
+
let hoursUntilOpen;
|
|
33
|
+
let hoursUntilClose;
|
|
34
|
+
const candidates = [hour, hour + 24];
|
|
35
|
+
for (const h of candidates) {
|
|
36
|
+
if (h >= s.openHourJst && h < s.closeHourJst) {
|
|
37
|
+
state = "open";
|
|
38
|
+
hoursUntilClose = s.closeHourJst - h;
|
|
39
|
+
return { session: s, state, hoursUntilClose };
|
|
40
|
+
}
|
|
41
|
+
const delta = s.openHourJst - h;
|
|
42
|
+
if (delta > 0 && delta <= 0.5) {
|
|
43
|
+
state = "pre-open";
|
|
44
|
+
hoursUntilOpen = delta;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return { session: s, state, hoursUntilOpen, hoursUntilClose };
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=sessions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/lib/sessions.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,iDAAiD;AACjD,0BAA0B;AAU1B,yBAAyB;AACzB,qBAAqB;AACrB,sBAAsB;AACtB,qDAAqD;AACrD,oDAAoD;AACpD,MAAM,CAAC,MAAM,eAAe,GAA6B;IACvD,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE;IAChE,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE;IACpE,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;IACpE,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE;CAC/D,CAAC;AAWF,6BAA6B;AAC7B,gDAAgD;AAChD,MAAM,UAAU,kBAAkB,CAAC,MAAY,IAAI,IAAI,EAAE;IACvD,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;IAC9C,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,oBAAoB;IACvD,MAAM,SAAS,GAAG,SAAS,KAAK,CAAC,IAAI,SAAS,KAAK,CAAC,CAAC;IACrD,wCAAwC;IACxC,6CAA6C;IAC7C,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,aAAa,EAAE,GAAG,EAAE,CAAC;IAC1D,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAiB,EAAE;QAC9C,IAAI,SAAS,EAAE,CAAC;YACd,wCAAwC;YACxC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;QACzC,CAAC;QACD,kCAAkC;QAClC,IAAI,KAAK,GAA2B,QAAQ,CAAC;QAC7C,IAAI,cAAkC,CAAC;QACvC,IAAI,eAAmC,CAAC;QACxC,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;QACrC,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,CAAC,WAAW,IAAI,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,CAAC;gBAC7C,KAAK,GAAG,MAAM,CAAC;gBACf,eAAe,GAAG,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC;gBACrC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;YAChD,CAAC;YACD,MAAM,KAAK,GAAG,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC;YAChC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;gBAC9B,KAAK,GAAG,UAAU,CAAC;gBACnB,cAAc,GAAG,KAAK,CAAC;YACzB,CAAC;QACH,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,CAAC;IAChE,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/lib/sma.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// 単純移動平均(SMA)の計算純関数。
|
|
2
|
+
// PeriodChart の 50 日 / 200 日線オーバーレイ、quartile.ts の 200 日線クロス検出、
|
|
3
|
+
// rankings.ts の期間別パフォーマンス計算などで共通利用する。
|
|
4
|
+
// 配列に対する N 期間 SMA を返す。先頭 N-1 個は null(データ不足)。
|
|
5
|
+
export function rollingSMA(values, window) {
|
|
6
|
+
if (window <= 0)
|
|
7
|
+
return values.map(() => null);
|
|
8
|
+
const out = [];
|
|
9
|
+
let sum = 0;
|
|
10
|
+
for (let i = 0; i < values.length; i++) {
|
|
11
|
+
sum += values[i];
|
|
12
|
+
if (i >= window)
|
|
13
|
+
sum -= values[i - window];
|
|
14
|
+
if (i >= window - 1) {
|
|
15
|
+
out.push(sum / window);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
out.push(null);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return out;
|
|
22
|
+
}
|
|
23
|
+
// 末尾 N 期間の SMA 単一値。データ不足は null。
|
|
24
|
+
export function lastSMA(values, window) {
|
|
25
|
+
if (values.length < window || window <= 0)
|
|
26
|
+
return null;
|
|
27
|
+
let sum = 0;
|
|
28
|
+
for (let i = values.length - window; i < values.length; i++) {
|
|
29
|
+
sum += values[i];
|
|
30
|
+
}
|
|
31
|
+
return sum / window;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=sma.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sma.js","sourceRoot":"","sources":["../../src/lib/sma.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,+DAA+D;AAC/D,sCAAsC;AAEtC,6CAA6C;AAC7C,MAAM,UAAU,UAAU,CACxB,MAAyB,EACzB,MAAc;IAEd,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAsB,EAAE,CAAC;IAClC,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;QACjB,IAAI,CAAC,IAAI,MAAM;YAAE,GAAG,IAAI,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,CAAC;QACzB,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,gCAAgC;AAChC,MAAM,UAAU,OAAO,CACrB,MAAyB,EACzB,MAAc;IAEd,IAAI,MAAM,CAAC,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACvD,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5D,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,GAAG,GAAG,MAAM,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Snapshot } from "./market-types.js";
|
|
2
|
+
export type ThermometerComponent = {
|
|
3
|
+
label: string;
|
|
4
|
+
value: number | null;
|
|
5
|
+
bias: string;
|
|
6
|
+
};
|
|
7
|
+
export type ThermometerResult = {
|
|
8
|
+
score: number;
|
|
9
|
+
level: "risk-on" | "neutral" | "risk-off";
|
|
10
|
+
components: ThermometerComponent[];
|
|
11
|
+
};
|
|
12
|
+
export declare function computeThermometer(snapshot: Snapshot): ThermometerResult | null;
|
|
13
|
+
export declare function computeThermometerHistory(snapshot: Snapshot, days?: number): number[];
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// マーケット温度計:複数指標を組み合わせて 0〜100 のリスクオン/オフ合成スコアを返す。
|
|
2
|
+
// 数値の意味は「リスクオン度」(=積極的にリスク資産が買われている度合い)。
|
|
3
|
+
// 高い (>= 70) → リスクオン優勢、低い (<= 30) → リスクオフ優勢、中間 → 中立。
|
|
4
|
+
//
|
|
5
|
+
// あくまで個々の指標の現在値を線形マッピングして平均する素朴な合成で、
|
|
6
|
+
// 「これを根拠に売買せよ」という投資シグナルではない(YMYL 配慮)。
|
|
7
|
+
// 算出式・ラベルは事実ベースに留め、UI 側でも「投資助言ではなく俯瞰用」と明示する。
|
|
8
|
+
// 値を 0..100 にクリップ
|
|
9
|
+
function clamp01(x) {
|
|
10
|
+
return Math.max(0, Math.min(100, x));
|
|
11
|
+
}
|
|
12
|
+
function getQuote(snapshot, symbol) {
|
|
13
|
+
const q = snapshot.quotes[symbol];
|
|
14
|
+
if (!q || "error" in q)
|
|
15
|
+
return null;
|
|
16
|
+
return q;
|
|
17
|
+
}
|
|
18
|
+
// VIX:低いほどリスクオン。10 → 100、30 → 0 で線形マッピング。
|
|
19
|
+
// (20 が中立 50 になるよう設計)
|
|
20
|
+
function vixScore(snapshot) {
|
|
21
|
+
const q = getQuote(snapshot, "^VIX");
|
|
22
|
+
if (!q)
|
|
23
|
+
return null;
|
|
24
|
+
const v = q.price;
|
|
25
|
+
return clamp01(((30 - v) / 20) * 100);
|
|
26
|
+
}
|
|
27
|
+
// S&P 500 前日比:+1.5% で 100、-1.5% で 0、0% で 50。
|
|
28
|
+
function spxScore(snapshot) {
|
|
29
|
+
const q = getQuote(snapshot, "^GSPC");
|
|
30
|
+
if (!q)
|
|
31
|
+
return null;
|
|
32
|
+
return clamp01(((q.changePercent + 1.5) / 3) * 100);
|
|
33
|
+
}
|
|
34
|
+
// 米10年金利:金利上昇 = リスクオン側に振れることが多い(景気期待)が、過熱で逆相関にもなる。
|
|
35
|
+
// ここでは前日比 bp で評価:+10bp で 100、-10bp で 0、0bp で 50。
|
|
36
|
+
function tnxScore(snapshot) {
|
|
37
|
+
const q = getQuote(snapshot, "^TNX");
|
|
38
|
+
if (!q)
|
|
39
|
+
return null;
|
|
40
|
+
return clamp01(((q.changeBp + 10) / 20) * 100);
|
|
41
|
+
}
|
|
42
|
+
// ドル指数 DXY:上昇は一般にリスクオフ(質への逃避)。前日比 -0.5% で 100、+0.5% で 0、0% で 50。
|
|
43
|
+
function dxyScore(snapshot) {
|
|
44
|
+
const q = getQuote(snapshot, "DX-Y.NYB");
|
|
45
|
+
if (!q)
|
|
46
|
+
return null;
|
|
47
|
+
return clamp01(((-q.changePercent + 0.5) / 1) * 100);
|
|
48
|
+
}
|
|
49
|
+
// /today 上部に出すマーケット温度計の合成スコアを返す。
|
|
50
|
+
// 取得できた成分の平均で算出する(欠損成分は無視)。全成分欠損なら null。
|
|
51
|
+
export function computeThermometer(snapshot) {
|
|
52
|
+
const components = [
|
|
53
|
+
{ label: "VIX (株式ボラ)", value: vixScore(snapshot), bias: "低いほどリスクオン" },
|
|
54
|
+
{ label: "S&P 500 前日比", value: spxScore(snapshot), bias: "上昇でリスクオン" },
|
|
55
|
+
{ label: "米10年金利前日比", value: tnxScore(snapshot), bias: "上昇でリスクオン寄り" },
|
|
56
|
+
{ label: "ドル指数前日比", value: dxyScore(snapshot), bias: "下落でリスクオン" },
|
|
57
|
+
];
|
|
58
|
+
const valid = components
|
|
59
|
+
.map((c) => c.value)
|
|
60
|
+
.filter((v) => v !== null);
|
|
61
|
+
if (valid.length === 0)
|
|
62
|
+
return null;
|
|
63
|
+
const score = valid.reduce((a, b) => a + b, 0) / valid.length;
|
|
64
|
+
const level = score >= 70 ? "risk-on" : score <= 30 ? "risk-off" : "neutral";
|
|
65
|
+
return { score, level, components };
|
|
66
|
+
}
|
|
67
|
+
// 任意の VIX 価格 / SPX・DXY 前日比% / TNX bp から合成スコアを計算(履歴算出用)。
|
|
68
|
+
function scoreFromValues(vixPrice, spxPct, tnxBp, dxyPct) {
|
|
69
|
+
const parts = [];
|
|
70
|
+
if (typeof vixPrice === "number")
|
|
71
|
+
parts.push(clamp01(((30 - vixPrice) / 20) * 100));
|
|
72
|
+
if (typeof spxPct === "number")
|
|
73
|
+
parts.push(clamp01(((spxPct + 1.5) / 3) * 100));
|
|
74
|
+
if (typeof tnxBp === "number")
|
|
75
|
+
parts.push(clamp01(((tnxBp + 10) / 20) * 100));
|
|
76
|
+
if (typeof dxyPct === "number")
|
|
77
|
+
parts.push(clamp01(((-dxyPct + 0.5) / 1) * 100));
|
|
78
|
+
if (parts.length === 0)
|
|
79
|
+
return null;
|
|
80
|
+
return parts.reduce((a, b) => a + b, 0) / parts.length;
|
|
81
|
+
}
|
|
82
|
+
// 過去 N 日の温度計合成スコアを日足配列から逆算する。
|
|
83
|
+
// closes1y を持つ 4 銘柄(^VIX, ^GSPC, ^TNX, DX-Y.NYB)の close 配列を入力に取り、
|
|
84
|
+
// 各日 i について closes[i] と closes[i-1] から prev-day 比を計算してスコア化。
|
|
85
|
+
// 戻り値は末尾が「最新日」、長さは days (データ点不足は number[] が短くなる)。
|
|
86
|
+
export function computeThermometerHistory(snapshot, days = 30) {
|
|
87
|
+
const get1y = (symbol) => {
|
|
88
|
+
const q = snapshot.quotes[symbol];
|
|
89
|
+
if (!q || "error" in q)
|
|
90
|
+
return null;
|
|
91
|
+
return q.closes1y && q.closes1y.length > 1 ? q.closes1y : null;
|
|
92
|
+
};
|
|
93
|
+
const vix = get1y("^VIX");
|
|
94
|
+
const spx = get1y("^GSPC");
|
|
95
|
+
const tnx = get1y("^TNX");
|
|
96
|
+
const dxy = get1y("DX-Y.NYB");
|
|
97
|
+
// 共通する有効長を取る(最も短い配列に合わせる、ただし null は無視)
|
|
98
|
+
const lens = [vix, spx, tnx, dxy]
|
|
99
|
+
.filter((a) => a !== null)
|
|
100
|
+
.map((a) => a.length);
|
|
101
|
+
if (lens.length === 0)
|
|
102
|
+
return [];
|
|
103
|
+
const minLen = Math.min(...lens);
|
|
104
|
+
// i=1 から minLen-1 までスコア化(i=0 は前日が無い)
|
|
105
|
+
const start = Math.max(1, minLen - days);
|
|
106
|
+
const out = [];
|
|
107
|
+
for (let i = start; i < minLen; i++) {
|
|
108
|
+
const vixPrice = vix ? vix[i] : null;
|
|
109
|
+
const spxPct = spx && spx[i - 1] !== 0 ? ((spx[i] - spx[i - 1]) / spx[i - 1]) * 100 : null;
|
|
110
|
+
const tnxBp = tnx ? (tnx[i] - tnx[i - 1]) * 100 : null;
|
|
111
|
+
const dxyPct = dxy && dxy[i - 1] !== 0 ? ((dxy[i] - dxy[i - 1]) / dxy[i - 1]) * 100 : null;
|
|
112
|
+
const s = scoreFromValues(vixPrice, spxPct, tnxBp, dxyPct);
|
|
113
|
+
if (s !== null)
|
|
114
|
+
out.push(s);
|
|
115
|
+
}
|
|
116
|
+
return out;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=thermometer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thermometer.js","sourceRoot":"","sources":["../../src/lib/thermometer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Indicator, Quote, QuoteResult, Snapshot } from "./market-types.js";
|
|
2
|
+
export declare class YahooFinanceError extends Error {
|
|
3
|
+
readonly symbol: string;
|
|
4
|
+
readonly status: number;
|
|
5
|
+
constructor(symbol: string, status: number, message?: string);
|
|
6
|
+
}
|
|
7
|
+
export declare function fetchHistorical(symbol: string): Promise<number[]>;
|
|
8
|
+
export declare function fetchQuoteForIndicator(indicator: Indicator): Promise<QuoteResult>;
|
|
9
|
+
export declare function fetchQuoteBySymbol(symbol: string): Promise<Quote>;
|
|
10
|
+
export declare function fetchSnapshot(): Promise<Snapshot>;
|
|
11
|
+
export declare function fetchSubsetSnapshot(symbols: readonly string[]): Promise<Record<string, QuoteResult>>;
|