Skip to content

Commit 8633e9b

Browse files
committed
Used PineData as indicator tvar's element.
1 parent a8ac395 commit 8633e9b

16 files changed

+305
-171
lines changed

src/lib/charting/plot/Plot.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
1-
import type { TimeData } from "../../domain/Kline";
2-
3-
export type PlotData = {
4-
time?: number,
5-
value: unknown
6-
}
1+
import type { PineData } from "../../domain/PineData";
72

83
export type Plot = {
9-
data: PlotData[],
4+
data: PineData[],
105
options: PlotOptions | PlotCharOptions | PlotShapeOptions,
116
title: string,
12-
plot1: TimeData[], // plot1 for fill
13-
plot2: TimeData[], // plot2 for fill
7+
plot1: PineData[], // plot1 for fill
8+
plot2: PineData[], // plot2 for fill
149
}
1510

1611
export type PlotCharOptions = {
@@ -48,6 +43,7 @@ export type PlotOptions = {
4843
format?: string;
4944
precision?: number;
5045
force_overlay?: boolean;
46+
fillgaps?: boolean;
5147
location?: Location; // added by me, may need to remove
5248
};
5349

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import type { PineData } from "../../domain/PineData";
2+
import { Path } from "../../svg/Path";
3+
import type { TVar } from "../../timeseris/TVar";
4+
import type { ChartXControl } from "../view/ChartXControl";
5+
import type { ChartYControl } from "../view/ChartYControl";
6+
import type { PlotOptions } from "./Plot";
7+
8+
type Props = {
9+
xc: ChartXControl,
10+
yc: ChartYControl,
11+
tvar: TVar<PineData[]>,
12+
name: string,
13+
atIndex: number,
14+
options: PlotOptions;
15+
depth?: number;
16+
}
17+
18+
const PlotBgcolor = (props: Props) => {
19+
const { xc, yc, tvar, atIndex } = props;
20+
21+
function plot() {
22+
const thin = false
23+
24+
const posPath = new Path()
25+
const negPath = new Path()
26+
27+
const r = xc.wBar < 2
28+
? 0
29+
: Math.floor((xc.wBar - 2) / 2);
30+
31+
for (let bar = 1; bar <= xc.nBars; bar++) {
32+
const time = xc.tb(bar)
33+
if (tvar.occurred(time)) {
34+
const datas = tvar.getByTime(time);
35+
const data = datas ? datas[atIndex] : undefined;
36+
const v = data?.options?.color
37+
}
38+
39+
// if (!(max === 0 && min === 0)) {
40+
// let yValue = 0;
41+
// let yDatum = 0;
42+
// let path: Path;
43+
// if (Math.abs(max) > Math.abs(min)) {
44+
// path = posPath;
45+
// yValue = yc.yv(max);
46+
// yDatum = yc.yv(min);
47+
// } else {
48+
// path = negPath;
49+
// yValue = yc.yv(min)
50+
// yDatum = yc.yv(max)
51+
// }
52+
53+
// const x = xc.xb(bar)
54+
55+
// if (thin || xc.wBar <= 2) {
56+
// path.moveto(x, yDatum);
57+
// path.lineto(x, yValue);
58+
59+
// } else {
60+
// path.moveto(x - r, yDatum)
61+
// path.lineto(x - r, yValue)
62+
// path.lineto(x + r, yValue)
63+
// path.lineto(x + r, yDatum)
64+
// }
65+
// }
66+
67+
}
68+
69+
return { posPath, negPath }
70+
}
71+
72+
const { posPath, negPath } = plot();
73+
74+
return (
75+
<g className="volumechart">
76+
{posPath.render({ className: 'positive' })}
77+
{negPath.render({ className: 'negative' })}
78+
</g>
79+
)
80+
}
81+
82+
export default PlotBgcolor;

src/lib/charting/plot/PlotCrossCircles.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ import type { ChartXControl } from "../view/ChartXControl";
55
import type { Seg } from "../../svg/Seg";
66
import { Circle } from "../../svg/Circle";
77
import type { PlotOptions } from "./Plot";
8+
import type { PineData } from "../../domain/PineData";
89

910
type Props = {
1011
xc: ChartXControl,
1112
yc: ChartYControl,
12-
tvar: TVar<unknown[]>,
13+
tvar: TVar<PineData[]>,
1314
name: string,
1415
atIndex: number,
1516
options: PlotOptions;
@@ -39,22 +40,23 @@ const PlotCrossCircles = (props: Props) => {
3940

4041
// For those need connect from one bar to the next, use bar++ instead of
4142
// bar += xc.nBarsCompressed to avoid uncontinuted line.
42-
for (let bar = 1; bar <= xc.nBars; bar++) {
43-
// use `undefiend` to test if value has been set at least one time
43+
for (let bar = 1; bar <= xc.nBars; bar += xc.nBarsCompressed) {
44+
// use `undefined` to test if value has been set at least one time
4445
const vs: number[] = []
4546
for (let i = 0; i < xc.nBarsCompressed; i++) {
4647
const time = xc.tb(bar + i)
4748
if (tvar.occurred(time)) {
48-
const values = tvar.getByTime(time);
49-
const v = values ? values[atIndex] : NaN;
50-
if (typeof v === "number" && isNaN(v) === false) {
49+
const datas = tvar.getByTime(time);
50+
const data = datas ? datas[atIndex] : undefined;
51+
const v = data ? data.value : NaN
52+
if (typeof v === "number" && !isNaN(v)) {
5153
vs.push(v)
5254
}
5355
}
5456
}
5557

5658
for (const value of vs) {
57-
if (value !== undefined && isNaN(value) === false) {
59+
if (value !== undefined && !isNaN(value)) {
5860
y2 = yc.yv(value)
5961
// x1 shoud be decided here, it may not equal prev x2:
6062
// think about the case of on calendar day mode
@@ -85,7 +87,7 @@ const PlotCrossCircles = (props: Props) => {
8587
const { segs } = plot();
8688

8789
return (
88-
segs.map((seg, n) => seg.render({ key: 'seg-' + n, style: { stroke: options.color, fill: options.color } }))
90+
segs.map((seg, n) => seg.render({ key: 'seg-' + n, style: { stroke: options.color, fill: 'none' } }))
8991
)
9092
}
9193

src/lib/charting/plot/PlotFill.tsx

Lines changed: 60 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,49 +3,79 @@ import { Path } from "../../svg/Path";
33
import type { ChartYControl } from "../view/ChartYControl";
44
import type { ChartXControl } from "../view/ChartXControl";
55
import type { PlotOptions } from "./Plot";
6-
import type { TimeData } from "../../domain/Kline";
6+
import type { PineData } from "../../domain/PineData";
7+
import type { Seg } from "../../svg/Seg";
78

89
type Props = {
910
xc: ChartXControl,
1011
yc: ChartYControl,
11-
tvar: TVar<unknown[]>,
12+
tvar: TVar<PineData[]>,
1213
name: string,
1314
options: PlotOptions;
14-
plot1: TimeData[];
15-
plot2: TimeData[];
15+
plot1: PineData[];
16+
plot2: PineData[];
1617
depth?: number;
1718
}
1819

1920
const PlotFill = (props: Props) => {
2021
const { xc, yc, tvar, name, depth, plot1, plot2, options } = props;
2122

23+
const fillgaps = options.fillgaps;
24+
25+
const r = xc.wBar < 2
26+
? 0
27+
: Math.floor((xc.wBar - 2) / 2);
28+
2229
function plot() {
23-
const path = new Path();
24-
const points_a = linePoints(plot1);
25-
const points_b = linePoints(plot2).reverse();
26-
const points = [...points_a, ...points_b]
27-
28-
for (let i = 0; i < points.length; i++) {
29-
const [x, y] = points[i]
30-
if (i === 0) {
31-
path.moveto(x, y)
30+
const segs: Seg[] = [];
31+
const points_a = collectPoints(plot1);
32+
const points_b = collectPoints(plot2)
33+
34+
let shallStartNewFill = true
35+
36+
let unClosedPath: Path
37+
let lastCloseIndex = 0
38+
for (let m = 0; m < points_a.length; m++) {
39+
const [xa, ya] = points_a[m]
40+
const [xb, yb] = points_b[m]
41+
42+
if (xa === undefined || xb === undefined) {
43+
if (unClosedPath) {
44+
for (let n = m - 1; n > lastCloseIndex; n--) {
45+
const [xb, yb] = points_b[n]
46+
unClosedPath.lineto(xb, yb)
47+
}
48+
49+
unClosedPath.closepath()
50+
}
51+
52+
shallStartNewFill = true
53+
3254
} else {
33-
path.lineto(x, y)
55+
if (shallStartNewFill) {
56+
unClosedPath = new Path()
57+
segs.push(unClosedPath)
58+
59+
unClosedPath.moveto(xa, ya)
60+
61+
lastCloseIndex = m
62+
shallStartNewFill = false
63+
64+
} else {
65+
unClosedPath.lineto(xa, ya)
66+
}
67+
3468
}
3569
}
3670

37-
path.closepath()
38-
39-
return { path }
71+
return { segs }
4072
}
4173

42-
function linePoints(datas: TimeData[]) {
74+
function collectPoints(datas: PineData[]) {
4375
const points: number[][] = []
4476

45-
// For those need connect from one bar to the next, use bar++ instead of
46-
// bar += xc.nBarsCompressed to avoid uncontinuted line.
4777
for (let bar = 1; bar <= xc.nBars; bar++) {
48-
// use `undefiend` to test if value has been set at least one time
78+
// use `undefined` to test if value has been set at least one time
4979
let value: number
5080
const time = xc.tb(bar)
5181
if (tvar.occurred(time)) {
@@ -55,28 +85,33 @@ const PlotFill = (props: Props) => {
5585

5686
// console.log(index, data)
5787

58-
if (typeof v === "number" && isNaN(v) === false) {
88+
if (typeof v === "number" && !isNaN(v)) {
5989
value = v;
6090
}
6191
}
6292

63-
if (value !== undefined && isNaN(value) === false) {
93+
if (value !== undefined && !isNaN(value)) {
6494
const x = xc.xb(bar)
6595
const y = yc.yv(value)
6696

6797
if (y !== undefined && !isNaN(y)) {
6898
points.push([x, y])
6999
}
100+
101+
} else {
102+
if (!fillgaps) {
103+
points.push([undefined, undefined])
104+
}
70105
}
71106
}
72107

73108
return points
74109
}
75110

76-
const { path } = plot();
111+
const { segs } = plot();
77112

78113
return (
79-
path.render({ style: { stroke: options.color, fill: options.color } })
114+
segs.map((seg, n) => seg.render({ key: 'seg-' + n, style: { stroke: undefined, fill: options.color } }))
80115
)
81116
}
82117

src/lib/charting/plot/PlotHistogram.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { PineData } from "../../domain/PineData";
12
import { Path } from "../../svg/Path";
23
import type { TVar } from "../../timeseris/TVar";
34
import type { ChartXControl } from "../view/ChartXControl";
@@ -7,7 +8,7 @@ import type { PlotOptions } from "./Plot";
78
type Props = {
89
xc: ChartXControl,
910
yc: ChartYControl,
10-
tvar: TVar<unknown[]>,
11+
tvar: TVar<PineData[]>,
1112
name: string,
1213
atIndex: number,
1314
options: PlotOptions;
@@ -33,9 +34,10 @@ const PlotHistogram = (props: Props) => {
3334
for (let i = 0; i < xc.nBarsCompressed; i++) {
3435
const time = xc.tb(bar + i)
3536
if (tvar.occurred(time)) {
36-
const values = tvar.getByTime(time);
37-
const v = values ? values[atIndex] : NaN;
38-
if (typeof v === "number" && isNaN(v) === false) {
37+
const datas = tvar.getByTime(time);
38+
const data = datas ? datas[atIndex] : undefined;
39+
const v = data ? data.value : NaN;
40+
if (typeof v === "number" && !isNaN(v)) {
3941
max = Math.max(max, v);
4042
min = Math.min(min, v);
4143
}

src/lib/charting/plot/PlotHline.tsx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ import type { ChartYControl } from "../view/ChartYControl";
44
import type { ChartXControl } from "../view/ChartXControl";
55
import type { Seg } from "../../svg/Seg";
66
import type { PlotOptions } from "./Plot";
7+
import type { PineData } from "../../domain/PineData";
78

89
type Props = {
910
xc: ChartXControl,
1011
yc: ChartYControl,
11-
tvar: TVar<unknown[]>,
12+
tvar: TVar<PineData[]>,
1213
name: string,
1314
atIndex: number,
1415
options: PlotOptions,
@@ -46,15 +47,14 @@ const PlotHline = (props: Props) => {
4647
// bar += xc.nBarsCompressed to avoid uncontinuted line.
4748
let value: number;
4849
for (let bar = 1; bar <= xc.nBars; bar++) {
49-
for (let i = 0; i < xc.nBarsCompressed; i++) {
50-
const time = xc.tb(bar + i)
51-
if (tvar.occurred(time)) {
52-
const values = tvar.getByTime(time);
53-
const v = values ? values[atIndex] : NaN;
54-
if (typeof v === "number" && isNaN(v) === false) {
55-
value = v;
56-
break;
57-
}
50+
const time = xc.tb(bar)
51+
if (tvar.occurred(time)) {
52+
const datas = tvar.getByTime(time);
53+
const data = datas ? datas[atIndex] : undefined;
54+
const v = data ? data.value : NaN
55+
if (typeof v === "number" && !isNaN(v)) {
56+
value = v;
57+
break;
5858
}
5959
}
6060
}
@@ -69,7 +69,7 @@ const PlotHline = (props: Props) => {
6969
const { segs } = plot();
7070

7171
return (
72-
segs.map((seg, n) => seg.render({ key: 'seg-' + n, style: { stroke: options.color, fill: options.color, strokeDasharray } }))
72+
segs.map((seg, n) => seg.render({ key: 'seg-' + n, style: { stroke: options.color, fill: 'none', strokeDasharray } }))
7373
)
7474
}
7575

src/lib/charting/plot/PlotKline.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const PlotKline = (props: Props) => {
4444
function plotCandleOrBar(kind: KlineKind, posPath: Path, negPath: Path) {
4545

4646
for (let bar = 1; bar <= xc.nBars; bar += xc.nBarsCompressed) {
47-
// use `undefiend` to test if value has been set at least one time
47+
// use `undefined` to test if value has been set at least one time
4848
let open: number = undefined
4949
let close: number = undefined
5050
let high = Number.NEGATIVE_INFINITY;

0 commit comments

Comments
 (0)