react-financial-charts
Version:
React charts specific to finance.
129 lines • 5.4 kB
JavaScript
import { deviation, sum, zip } from "d3-array";
import { path as d3Path } from "d3-path";
import * as React from "react";
import GenericChartComponent from "../../GenericChartComponent";
import { getMouseCanvas } from "../../GenericComponent";
import { isHovering2 } from "./StraightLine";
import { colorToRGBA, getClosestItemIndexes, isDefined, noop } from "../../utils";
export class LinearRegressionChannelWithArea extends React.Component {
constructor() {
super(...arguments);
this.renderSVG = (moreProps) => {
const { stroke, strokeWidth, fillOpacity, strokeOpacity, fill } = this.props;
const { x1, y1, x2, y2, dy } = helper(this.props, moreProps);
const line = {
strokeWidth,
stroke,
strokeOpacity,
};
const ctx = d3Path();
ctx.moveTo(x1, y1 - dy);
ctx.lineTo(x2, y2 - dy);
ctx.lineTo(x2, y2 + dy);
ctx.lineTo(x1, y1 + dy);
ctx.closePath();
return (React.createElement("g", null,
React.createElement("line", Object.assign({}, line, { x1: x1, y1: y1 - dy, x2: x2, y2: y2 - dy })),
React.createElement("line", Object.assign({}, line, { x1: x1, y1: y1 + dy, x2: x2, y2: y2 + dy })),
React.createElement("path", { d: ctx.toString(), fill: fill, fillOpacity: fillOpacity }),
React.createElement("line", Object.assign({}, line, { x1: x1, y1: y1, x2: x2, y2: y2 }))));
};
this.drawOnCanvas = (ctx, moreProps) => {
const { stroke, strokeWidth, fillOpacity, strokeOpacity, fill } = this.props;
const { x1, y1, x2, y2, dy } = helper(this.props, moreProps);
ctx.lineWidth = strokeWidth;
ctx.strokeStyle = colorToRGBA(stroke, strokeOpacity);
ctx.fillStyle = colorToRGBA(fill, fillOpacity);
ctx.beginPath();
ctx.moveTo(x1, y1 - dy);
ctx.lineTo(x2, y2 - dy);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(x2, y2 + dy);
ctx.lineTo(x1, y1 + dy);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(x1, y1 - dy);
ctx.lineTo(x2, y2 - dy);
ctx.lineTo(x2, y2 + dy);
ctx.lineTo(x1, y1 + dy);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.moveTo(x2, y2);
ctx.lineTo(x1, y1);
ctx.stroke();
};
this.isHover = (moreProps) => {
const { tolerance, onHover } = this.props;
if (isDefined(onHover)) {
const { mouseXY } = moreProps;
const { x1, y1, x2, y2, dy } = helper(this.props, moreProps);
const yDiffs = [-dy, 0, dy];
const hovering = yDiffs.reduce((result, diff) => result || isHovering2([x1, y1 + diff], [x2, y2 + diff], mouseXY, tolerance), false);
return hovering;
}
return false;
};
}
render() {
const { selected, interactiveCursorClass } = this.props;
const { onHover, onUnHover } = this.props;
return React.createElement(GenericChartComponent, { isHover: this.isHover, svgDraw: this.renderSVG, canvasToDraw: getMouseCanvas, canvasDraw: this.drawOnCanvas, interactiveCursorClass: interactiveCursorClass, selected: selected, onHover: onHover, onUnHover: onUnHover, drawOn: ["mousemove", "mouseleave", "pan", "drag"] });
}
}
LinearRegressionChannelWithArea.defaultProps = {
onDragStart: noop,
onDrag: noop,
onDragComplete: noop,
type: "SD",
strokeWidth: 1,
tolerance: 4,
selected: false,
};
export function edge1Provider(props) {
return function (moreProps) {
const { x1, y1 } = helper(props, moreProps);
return [x1, y1];
};
}
export function edge2Provider(props) {
return function (moreProps) {
const { x2, y2 } = helper(props, moreProps);
return [x2, y2];
};
}
function helper(props, moreProps) {
const { x1Value, x2Value, type } = props;
const { xScale, chartConfig: { yScale }, fullData } = moreProps;
const { xAccessor } = moreProps;
const { left } = getClosestItemIndexes(fullData, x1Value, xAccessor);
const { right } = getClosestItemIndexes(fullData, x2Value, xAccessor);
const startIndex = Math.min(left, right);
const endIndex = Math.max(left, right) + 1;
const array = fullData.slice(startIndex, endIndex);
const xs = array.map((d) => xAccessor(d).valueOf());
const ys = array.map((d) => d.close);
const n = array.length;
const xys = zip(xs, ys)
.map((d) => {
return d[0] * d[1];
});
const xSquareds = xs.map((x) => Math.pow(x, 2));
const b = (n * sum(xys) - sum(xs) * sum(ys)) / (n * sum(xSquareds) - Math.pow(sum(xs), 2));
const a = (sum(ys) - b * sum(xs)) / n;
const newy1 = a + b * x1Value;
const newy2 = a + b * x2Value;
const x1 = xScale(x1Value);
const y1 = yScale(newy1);
const x2 = xScale(x2Value);
const y2 = yScale(newy2);
const stdDev = type === "SD"
? deviation(array, (d) => d.close)
: 0;
const dy = yScale(newy1 - stdDev) - y1;
return {
x1, y1, x2, y2, dy,
};
}
//# sourceMappingURL=LinearRegressionChannelWithArea.js.map