모의투자, 백테스팅 레이아웃 수정
This commit is contained in:
@@ -40,9 +40,11 @@ function sparkPath(values: number[], w: number, h: number, min?: number, max?: n
|
||||
interface Props {
|
||||
market: string;
|
||||
timeframe?: Timeframe;
|
||||
/** 실시간 차트처럼 세로 스택 pane */
|
||||
stacked?: boolean;
|
||||
}
|
||||
|
||||
const PaperIndicatorPanel: React.FC<Props> = ({ market, timeframe = '1h' }) => {
|
||||
const PaperIndicatorPanel: React.FC<Props> = ({ market, timeframe = '1h', stacked = false }) => {
|
||||
const [rsi, setRsi] = React.useState<number[]>([]);
|
||||
const [macd, setMacd] = React.useState<number[]>([]);
|
||||
const [cci, setCci] = React.useState<number[]>([]);
|
||||
@@ -54,7 +56,7 @@ const PaperIndicatorPanel: React.FC<Props> = ({ market, timeframe = '1h' }) => {
|
||||
const bars = await fetchUpbitCandles(market, timeframe, 120);
|
||||
if (cancelled) return;
|
||||
const closes = bars.map(b => b.close);
|
||||
setRsi(computeRsi(closes).slice(-40));
|
||||
setRsi(computeRsi(closes).slice(-60));
|
||||
const ema = (arr: number[], p: number) => {
|
||||
const k = 2 / (p + 1);
|
||||
let v = arr[0];
|
||||
@@ -62,7 +64,7 @@ const PaperIndicatorPanel: React.FC<Props> = ({ market, timeframe = '1h' }) => {
|
||||
};
|
||||
const e12 = ema(closes, 12);
|
||||
const e26 = ema(closes, 26);
|
||||
setMacd(e12.slice(-40).map((v, i) => v - e26[closes.length - 40 + i]));
|
||||
setMacd(e12.slice(-60).map((v, i) => v - e26[closes.length - 60 + i]));
|
||||
const tp = bars.map(b => (b.high + b.low + b.close) / 3);
|
||||
const cciVals: number[] = [];
|
||||
for (let i = 20; i < tp.length; i++) {
|
||||
@@ -71,22 +73,25 @@ const PaperIndicatorPanel: React.FC<Props> = ({ market, timeframe = '1h' }) => {
|
||||
const md = slice.reduce((a, v) => a + Math.abs(v - sma), 0) / slice.length;
|
||||
cciVals.push(md === 0 ? 0 : (tp[i] - sma) / (0.015 * md));
|
||||
}
|
||||
setCci(cciVals.slice(-40));
|
||||
setCci(cciVals.slice(-60));
|
||||
} catch { /* ignore */ }
|
||||
})();
|
||||
return () => { cancelled = true; };
|
||||
}, [market, timeframe]);
|
||||
|
||||
const panels = useMemo(() => [
|
||||
{ label: 'RSI', values: rsi, color: '#a78bfa', ref: [30, 70] },
|
||||
{ label: 'RSI (14)', values: rsi, color: '#a78bfa', ref: [30, 70] as number[] },
|
||||
{ label: 'MACD', values: macd, color: '#38bdf8' },
|
||||
{ label: 'CCI', values: cci, color: '#fbbf24', ref: [-100, 100] },
|
||||
{ label: 'CCI (20)', values: cci, color: '#fbbf24', ref: [-100, 100] as number[] },
|
||||
], [rsi, macd, cci]);
|
||||
|
||||
const rootClass = stacked ? 'ptd-ind-stack' : 'ptd-indicators';
|
||||
const itemClass = stacked ? 'ptd-ind-row' : 'ptd-ind-panel';
|
||||
|
||||
return (
|
||||
<div className="ptd-indicators">
|
||||
<div className={rootClass}>
|
||||
{panels.map(p => (
|
||||
<div key={p.label} className="ptd-ind-panel">
|
||||
<div key={p.label} className={itemClass}>
|
||||
<div className="ptd-ind-label">{p.label}</div>
|
||||
<svg viewBox="0 0 120 48" className="ptd-ind-svg" preserveAspectRatio="none">
|
||||
{p.ref?.map((r, i) => {
|
||||
|
||||
Reference in New Issue
Block a user