lit-litelements 2.3.0 → 2.3.3
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/dist/component/candlestickPatterns.d.ts +13 -0
- package/dist/component/candlestickPatterns.js +89 -0
- package/dist/component/chart.lit.d.ts +8 -0
- package/dist/component/chart.lit.js +111 -9
- package/dist/main.d.ts +1 -0
- package/dist/main.js +9 -9
- package/package.json +1 -1
- package/readme.md +2 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare function isDoji(d: any): boolean;
|
|
2
|
+
export declare function isHammer(d: any): boolean;
|
|
3
|
+
export declare function isHangingMan(d: any): boolean;
|
|
4
|
+
export declare function isBullishEngulfing(prev: any, now: any): boolean;
|
|
5
|
+
export declare function isBearishEngulfing(prev: any, now: any): boolean;
|
|
6
|
+
export declare function isDarkCloud(prev: any, now: any): boolean;
|
|
7
|
+
export declare function isBullishPiercing(prev: any, now: any): boolean;
|
|
8
|
+
export declare function isHarami(prev: any, now: any): boolean;
|
|
9
|
+
export declare function isHaramiCross(prev: any, now: any): boolean;
|
|
10
|
+
export declare function isMorningStar(a: any, b: any, c: any): boolean;
|
|
11
|
+
export declare function isEveningStar(a: any, b: any, c: any): boolean;
|
|
12
|
+
export declare function isMorningDojiStar(a: any, b: any, c: any): boolean;
|
|
13
|
+
export declare function isEveningDojiStar(a: any, b: any, c: any): boolean;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// --- Candlestick Pattern Detection Helpers ---
|
|
2
|
+
export function isDoji(d) {
|
|
3
|
+
// const body = Math.abs(d.close - d.open);
|
|
4
|
+
// const range = d.high - d.low;
|
|
5
|
+
// return body / range < 0.1; // very small body relative to range
|
|
6
|
+
return d.close === d.open;
|
|
7
|
+
}
|
|
8
|
+
export function isHammer(d) {
|
|
9
|
+
const body = Math.abs(d.close - d.open);
|
|
10
|
+
const upperShadow = d.high - Math.max(d.close, d.open);
|
|
11
|
+
const lowerShadow = Math.min(d.close, d.open) - d.low;
|
|
12
|
+
return (lowerShadow > 2 * body) && (upperShadow < body);
|
|
13
|
+
}
|
|
14
|
+
export function isHangingMan(d) {
|
|
15
|
+
const body = Math.abs(d.close - d.open);
|
|
16
|
+
const upperShadow = d.high - Math.max(d.close, d.open);
|
|
17
|
+
const lowerShadow = Math.min(d.close, d.open) - d.low;
|
|
18
|
+
return (lowerShadow > 2 * body) && (upperShadow <= body) && (d.close < d.open);
|
|
19
|
+
}
|
|
20
|
+
export function isBullishEngulfing(prev, now) {
|
|
21
|
+
return (prev.close < prev.open && // previous candle red
|
|
22
|
+
now.close > now.open && // current candle green
|
|
23
|
+
now.open < prev.close &&
|
|
24
|
+
now.close > prev.open);
|
|
25
|
+
}
|
|
26
|
+
// Bearish Engulfing
|
|
27
|
+
export function isBearishEngulfing(prev, now) {
|
|
28
|
+
return (prev.close > prev.open && // prev green
|
|
29
|
+
now.close < now.open && // now red
|
|
30
|
+
now.open > prev.close &&
|
|
31
|
+
now.close < prev.open);
|
|
32
|
+
}
|
|
33
|
+
// Dark Cloud Cover
|
|
34
|
+
export function isDarkCloud(prev, now) {
|
|
35
|
+
const midpoint = (prev.open + prev.close) / 2;
|
|
36
|
+
return (prev.close > prev.open && // prev green
|
|
37
|
+
now.open > prev.high && // gap up
|
|
38
|
+
now.close < midpoint && // closes below midpoint
|
|
39
|
+
now.close > prev.open // but above prev open
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
// Bullish Piercing
|
|
43
|
+
export function isBullishPiercing(prev, now) {
|
|
44
|
+
const midpoint = (prev.open + prev.close) / 2;
|
|
45
|
+
return (prev.close < prev.open && // prev red
|
|
46
|
+
now.open < prev.low && // gap down
|
|
47
|
+
now.close > midpoint && // closes above midpoint
|
|
48
|
+
now.close < prev.open // but below prev open
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
// Harami (bearish or bullish depending on colors)
|
|
52
|
+
export function isHarami(prev, now) {
|
|
53
|
+
return ((prev.close > prev.open && now.close < now.open &&
|
|
54
|
+
now.open < prev.close && now.close > prev.open) || // bearish
|
|
55
|
+
(prev.close < prev.open && now.close > now.open &&
|
|
56
|
+
now.open > prev.close && now.close < prev.open) // bullish
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
// Harami Cross (small doji inside prior candle)
|
|
60
|
+
export function isHaramiCross(prev, now) {
|
|
61
|
+
const body = Math.abs(now.close - now.open);
|
|
62
|
+
return (body / (now.high - now.low) < 0.1 &&
|
|
63
|
+
now.high < Math.max(prev.open, prev.close) &&
|
|
64
|
+
now.low > Math.min(prev.open, prev.close));
|
|
65
|
+
}
|
|
66
|
+
// Morning Star (3-candle bullish reversal)
|
|
67
|
+
export function isMorningStar(a, b, c) {
|
|
68
|
+
return (a.close < a.open && // red
|
|
69
|
+
Math.abs(b.close - b.open) < (a.open - a.close) * 0.3 && // small candle
|
|
70
|
+
c.close > c.open && // green
|
|
71
|
+
c.close > (a.open + a.close) / 2 // closes well into body of first
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
// Evening Star (3-candle bearish reversal)
|
|
75
|
+
export function isEveningStar(a, b, c) {
|
|
76
|
+
return (a.close > a.open && // green
|
|
77
|
+
Math.abs(b.close - b.open) < (a.close - a.open) * 0.3 && // small candle
|
|
78
|
+
c.close < c.open && // red
|
|
79
|
+
c.close < (a.open + a.close) / 2 // closes well into body of first
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
// Morning Doji Star (doji middle candle)
|
|
83
|
+
export function isMorningDojiStar(a, b, c) {
|
|
84
|
+
return isMorningStar(a, b, c) && isDoji(b);
|
|
85
|
+
}
|
|
86
|
+
// Evening Doji Star (doji middle candle)
|
|
87
|
+
export function isEveningDojiStar(a, b, c) {
|
|
88
|
+
return isEveningStar(a, b, c) && isDoji(b);
|
|
89
|
+
}
|
|
@@ -9,6 +9,8 @@ interface StockData {
|
|
|
9
9
|
close: number;
|
|
10
10
|
MA20?: number;
|
|
11
11
|
MA5?: number;
|
|
12
|
+
MA9?: number;
|
|
13
|
+
MA15?: number;
|
|
12
14
|
MA10?: number;
|
|
13
15
|
MA50?: number;
|
|
14
16
|
MA200?: number;
|
|
@@ -19,6 +21,7 @@ interface StockData {
|
|
|
19
21
|
divergence?: number;
|
|
20
22
|
StochRSI_K?: number;
|
|
21
23
|
StochRSI_D?: number;
|
|
24
|
+
angleMACDsignal?: number | null;
|
|
22
25
|
}
|
|
23
26
|
declare class ChartElement extends LitElement {
|
|
24
27
|
stockData: StockData[];
|
|
@@ -32,12 +35,17 @@ declare class ChartElement extends LitElement {
|
|
|
32
35
|
id: string;
|
|
33
36
|
afterDraw: (chart: any) => void;
|
|
34
37
|
};
|
|
38
|
+
volume_Doji_915_Plugin: {
|
|
39
|
+
id: string;
|
|
40
|
+
afterDraw: (chart: any) => void;
|
|
41
|
+
};
|
|
35
42
|
_getChartData(): {
|
|
36
43
|
dates: string[];
|
|
37
44
|
closePrices: number[];
|
|
38
45
|
rsi: number[];
|
|
39
46
|
stochRSI_K: number[];
|
|
40
47
|
stochRSI_D: number[];
|
|
48
|
+
angleMACDsignal: number[];
|
|
41
49
|
ma5: number[];
|
|
42
50
|
ma10: number[];
|
|
43
51
|
ma20: number[];
|
|
@@ -20,6 +20,7 @@ import { LitElement, html } from "lit";
|
|
|
20
20
|
import Chart from "chart.js/auto";
|
|
21
21
|
import zoomPlugin from "chartjs-plugin-zoom";
|
|
22
22
|
import { customElement, property } from "lit/decorators.js";
|
|
23
|
+
import * as Patterns from "./candlestickPatterns";
|
|
23
24
|
let ChartElement = class ChartElement extends LitElement {
|
|
24
25
|
constructor() {
|
|
25
26
|
super(...arguments);
|
|
@@ -118,6 +119,74 @@ let ChartElement = class ChartElement extends LitElement {
|
|
|
118
119
|
}
|
|
119
120
|
},
|
|
120
121
|
};
|
|
122
|
+
// buy sell buy volume
|
|
123
|
+
this.volume_Doji_915_Plugin = {
|
|
124
|
+
id: "volumeSignalPlugin",
|
|
125
|
+
afterDraw: (chart) => {
|
|
126
|
+
const ctx = chart.ctx;
|
|
127
|
+
const { scales, data } = chart;
|
|
128
|
+
const closeDataset = data.datasets.find((ds) => ds.label === "Close Price");
|
|
129
|
+
const volumeDataset = data.datasets.find((ds) => ds.label === "Volume");
|
|
130
|
+
if (!closeDataset || !volumeDataset)
|
|
131
|
+
return;
|
|
132
|
+
const closeData = closeDataset.data;
|
|
133
|
+
const volumeData = volumeDataset.data;
|
|
134
|
+
for (let i = 5; i < closeData.length; i++) {
|
|
135
|
+
const candle = this.stockData[i];
|
|
136
|
+
const divergence = candle.divergence;
|
|
137
|
+
const isDoji = Patterns.isDoji(candle);
|
|
138
|
+
const isBull = candle.close > candle.open;
|
|
139
|
+
const isBear = candle.close < candle.open;
|
|
140
|
+
const x = scales.x.getPixelForValue(i);
|
|
141
|
+
const y = scales.yPrice.getPixelForValue(candle.close);
|
|
142
|
+
if (!candle)
|
|
143
|
+
continue;
|
|
144
|
+
const currentVolume = volumeData[i];
|
|
145
|
+
if (currentVolume == null)
|
|
146
|
+
continue;
|
|
147
|
+
// Average of previous 5 bars
|
|
148
|
+
const avgVolume =
|
|
149
|
+
// volumeData[i - 1]
|
|
150
|
+
(volumeData[i - 1] +
|
|
151
|
+
volumeData[i - 2] +
|
|
152
|
+
volumeData[i - 3] +
|
|
153
|
+
volumeData[i - 4] +
|
|
154
|
+
volumeData[i - 5]) / 5;
|
|
155
|
+
if (isDoji) {
|
|
156
|
+
ctx.beginPath();
|
|
157
|
+
ctx.arc(x, y, 4, 0, 2 * Math.PI);
|
|
158
|
+
ctx.fillStyle = "red";
|
|
159
|
+
ctx.fill();
|
|
160
|
+
ctx.fillStyle = "gray";
|
|
161
|
+
ctx.font = "10px sans-serif";
|
|
162
|
+
ctx.fillText("DOJI-REVERS", x + 6, y - 6);
|
|
163
|
+
}
|
|
164
|
+
if (currentVolume <= avgVolume * 1.5)
|
|
165
|
+
continue;
|
|
166
|
+
if (isBull &&
|
|
167
|
+
divergence != null &&
|
|
168
|
+
divergence > 0) {
|
|
169
|
+
ctx.beginPath();
|
|
170
|
+
ctx.arc(x, y, 4, 0, 2 * Math.PI);
|
|
171
|
+
ctx.fillStyle = "green";
|
|
172
|
+
ctx.fill();
|
|
173
|
+
ctx.fillStyle = "green";
|
|
174
|
+
ctx.font = "bold 12px sans-serif";
|
|
175
|
+
ctx.fillText("BUY_Vol", x + 6, y - 6);
|
|
176
|
+
}
|
|
177
|
+
if (isBear && divergence != null &&
|
|
178
|
+
divergence < 0) {
|
|
179
|
+
ctx.beginPath();
|
|
180
|
+
ctx.arc(x, y, 4, 0, 2 * Math.PI);
|
|
181
|
+
ctx.fillStyle = "red";
|
|
182
|
+
ctx.fill();
|
|
183
|
+
ctx.fillStyle = "red";
|
|
184
|
+
ctx.font = "bold 12px sans-serif";
|
|
185
|
+
ctx.fillText("SELL_Vol", x + 6, y - 6);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
};
|
|
121
190
|
}
|
|
122
191
|
firstUpdated() {
|
|
123
192
|
this._createChart();
|
|
@@ -159,6 +228,7 @@ let ChartElement = class ChartElement extends LitElement {
|
|
|
159
228
|
// ✅ StochRSI
|
|
160
229
|
stochRSI_K: this.stockData.map((d) => { var _a; return (_a = d.StochRSI_K) !== null && _a !== void 0 ? _a : null; }),
|
|
161
230
|
stochRSI_D: this.stockData.map((d) => { var _a; return (_a = d.StochRSI_D) !== null && _a !== void 0 ? _a : null; }),
|
|
231
|
+
angleMACDsignal: this.stockData.map((d) => { var _a; return (_a = d.angleMACDsignal) !== null && _a !== void 0 ? _a : null; }),
|
|
162
232
|
ma5: this.stockData.map((d) => { var _a; return (_a = d.MA5) !== null && _a !== void 0 ? _a : null; }),
|
|
163
233
|
ma10: this.stockData.map((d) => { var _a; return (_a = d.MA10) !== null && _a !== void 0 ? _a : null; }),
|
|
164
234
|
ma20: this.stockData.map((d) => { var _a; return (_a = d.MA20) !== null && _a !== void 0 ? _a : null; }),
|
|
@@ -177,7 +247,7 @@ let ChartElement = class ChartElement extends LitElement {
|
|
|
177
247
|
_updateChart() {
|
|
178
248
|
if (!this.chart)
|
|
179
249
|
return;
|
|
180
|
-
const { dates, closePrices, rsi, ma5, ma10, ma20, ma50, ma100, ma200, MACDLine, SignalLine, divergence, volumes, stochRSI_K, stochRSI_D, } = this._getChartData();
|
|
250
|
+
const { dates, closePrices, rsi, ma5, ma10, ma20, ma50, ma100, ma200, MACDLine, SignalLine, divergence, volumes, stochRSI_K, stochRSI_D, angleMACDsignal, } = this._getChartData();
|
|
181
251
|
this.chart.data.labels = dates;
|
|
182
252
|
const ds = this.chart.data.datasets;
|
|
183
253
|
ds[0].data = rsi;
|
|
@@ -195,6 +265,7 @@ let ChartElement = class ChartElement extends LitElement {
|
|
|
195
265
|
// ✅ Update StochRSI datasets (just like MACDLine and SignalLine)
|
|
196
266
|
ds[12].data = stochRSI_K; // %K line
|
|
197
267
|
ds[13].data = stochRSI_D; // %D line
|
|
268
|
+
ds[14].data = angleMACDsignal;
|
|
198
269
|
this.chart.update();
|
|
199
270
|
}
|
|
200
271
|
// --------------------------------------------------------------------
|
|
@@ -202,7 +273,7 @@ let ChartElement = class ChartElement extends LitElement {
|
|
|
202
273
|
// --------------------------------------------------------------------
|
|
203
274
|
_createChart() {
|
|
204
275
|
var _a;
|
|
205
|
-
const { dates, closePrices, rsi, ma5, ma10, ma20, ma50, ma100, ma200, MACDLine, SignalLine, divergence, volumes, stochRSI_K, stochRSI_D, } = this._getChartData();
|
|
276
|
+
const { dates, closePrices, rsi, ma5, ma10, ma20, ma50, ma100, ma200, MACDLine, SignalLine, divergence, volumes, stochRSI_K, stochRSI_D, angleMACDsignal } = this._getChartData();
|
|
206
277
|
const canvas = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.getElementById("stockChart");
|
|
207
278
|
if (!canvas)
|
|
208
279
|
return;
|
|
@@ -212,6 +283,7 @@ let ChartElement = class ChartElement extends LitElement {
|
|
|
212
283
|
// Register plugins
|
|
213
284
|
Chart.register(zoomPlugin);
|
|
214
285
|
// Chart.register(this.customLinePlugin);
|
|
286
|
+
Chart.register(this.volume_Doji_915_Plugin);
|
|
215
287
|
this.chart = new Chart(ctx, {
|
|
216
288
|
type: "line",
|
|
217
289
|
data: {
|
|
@@ -224,6 +296,7 @@ let ChartElement = class ChartElement extends LitElement {
|
|
|
224
296
|
borderColor: "rgba(61, 58, 215, 0.2)",
|
|
225
297
|
borderWidth: 1,
|
|
226
298
|
pointRadius: 0,
|
|
299
|
+
hidden: true, // <- hidden initially
|
|
227
300
|
},
|
|
228
301
|
{
|
|
229
302
|
label: "MACD Histogram",
|
|
@@ -272,8 +345,8 @@ let ChartElement = class ChartElement extends LitElement {
|
|
|
272
345
|
label: "MA50",
|
|
273
346
|
data: ma50,
|
|
274
347
|
yAxisID: "yPrice",
|
|
275
|
-
borderColor: "
|
|
276
|
-
borderWidth:
|
|
348
|
+
borderColor: "green",
|
|
349
|
+
borderWidth: 4,
|
|
277
350
|
pointRadius: 0,
|
|
278
351
|
},
|
|
279
352
|
{
|
|
@@ -288,8 +361,8 @@ let ChartElement = class ChartElement extends LitElement {
|
|
|
288
361
|
label: "MA200",
|
|
289
362
|
data: ma200,
|
|
290
363
|
yAxisID: "yPrice",
|
|
291
|
-
borderColor: "
|
|
292
|
-
borderWidth:
|
|
364
|
+
borderColor: "purple",
|
|
365
|
+
borderWidth: 3,
|
|
293
366
|
pointRadius: 0,
|
|
294
367
|
},
|
|
295
368
|
{
|
|
@@ -299,6 +372,7 @@ let ChartElement = class ChartElement extends LitElement {
|
|
|
299
372
|
borderColor: "#cc3333",
|
|
300
373
|
borderWidth: 1,
|
|
301
374
|
fill: false,
|
|
375
|
+
hidden: true, // <- hidden initially
|
|
302
376
|
},
|
|
303
377
|
{
|
|
304
378
|
label: "MA5",
|
|
@@ -307,6 +381,7 @@ let ChartElement = class ChartElement extends LitElement {
|
|
|
307
381
|
borderColor: "#111111",
|
|
308
382
|
borderWidth: 1,
|
|
309
383
|
fill: false,
|
|
384
|
+
hidden: true, // <- hidden initially
|
|
310
385
|
},
|
|
311
386
|
// Volume (bottom)
|
|
312
387
|
{
|
|
@@ -314,7 +389,22 @@ let ChartElement = class ChartElement extends LitElement {
|
|
|
314
389
|
data: volumes,
|
|
315
390
|
type: "bar",
|
|
316
391
|
yAxisID: "yVolume",
|
|
317
|
-
backgroundColor:
|
|
392
|
+
backgroundColor: (context) => {
|
|
393
|
+
const index = context.dataIndex;
|
|
394
|
+
const candle = this.stockData[index];
|
|
395
|
+
if (!candle)
|
|
396
|
+
return "rgba(128,128,128,0.5)";
|
|
397
|
+
const isBull = candle.close > candle.open;
|
|
398
|
+
const isBear = candle.close < candle.open;
|
|
399
|
+
if (isBull) {
|
|
400
|
+
return "rgba(0, 200, 0, 0.6)";
|
|
401
|
+
}
|
|
402
|
+
if (isBear) {
|
|
403
|
+
return "rgb(220, 0, 0)";
|
|
404
|
+
}
|
|
405
|
+
// Doji
|
|
406
|
+
return "black";
|
|
407
|
+
},
|
|
318
408
|
},
|
|
319
409
|
// StochRSI %K
|
|
320
410
|
{
|
|
@@ -322,8 +412,9 @@ let ChartElement = class ChartElement extends LitElement {
|
|
|
322
412
|
data: stochRSI_K,
|
|
323
413
|
yAxisID: "yStochRSI",
|
|
324
414
|
borderColor: "#00c853", // Green color for %K
|
|
325
|
-
borderWidth:
|
|
415
|
+
borderWidth: 1.5,
|
|
326
416
|
pointRadius: 0,
|
|
417
|
+
hidden: true, // <- hidden initially
|
|
327
418
|
},
|
|
328
419
|
// StochRSI %D
|
|
329
420
|
{
|
|
@@ -331,8 +422,19 @@ let ChartElement = class ChartElement extends LitElement {
|
|
|
331
422
|
data: stochRSI_D,
|
|
332
423
|
yAxisID: "yStochRSI",
|
|
333
424
|
borderColor: "#ff5252", // Red color for %D
|
|
334
|
-
borderWidth:
|
|
425
|
+
borderWidth: 1.5,
|
|
426
|
+
pointRadius: 0,
|
|
427
|
+
hidden: true, // <- hidden initially
|
|
428
|
+
},
|
|
429
|
+
// angleMACDsignal
|
|
430
|
+
{
|
|
431
|
+
label: "angleMACDsignal",
|
|
432
|
+
data: stochRSI_D,
|
|
433
|
+
yAxisID: "yMACD",
|
|
434
|
+
borderColor: "#ff5250", // Red color for %D
|
|
435
|
+
borderWidth: 1.5,
|
|
335
436
|
pointRadius: 0,
|
|
437
|
+
hidden: true, // <- hidden initially
|
|
336
438
|
},
|
|
337
439
|
],
|
|
338
440
|
},
|
package/dist/main.d.ts
CHANGED