추세검색 설정 추가
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import type { TrendSearchAppSettings } from '../../utils/trendSearchAppSettings';
|
||||
import {
|
||||
TREND_SEARCH_REFRESH_OPTIONS,
|
||||
formatTrendRefreshLabel,
|
||||
} from '../../utils/trendSearchAppSettings';
|
||||
import TrendSearchBullishWeightsSection from './TrendSearchBullishWeightsSection';
|
||||
|
||||
interface Props {
|
||||
settings: TrendSearchAppSettings;
|
||||
onChange: (next: TrendSearchAppSettings) => void;
|
||||
}
|
||||
|
||||
const SettingRow: React.FC<{
|
||||
label: string;
|
||||
desc?: string;
|
||||
children: React.ReactNode;
|
||||
}> = ({ label, desc, children }) => (
|
||||
<div className="stg-row">
|
||||
<div className="stg-row-label">
|
||||
<span className="stg-row-title">{label}</span>
|
||||
{desc && <span className="stg-row-desc">{desc}</span>}
|
||||
</div>
|
||||
<div className="stg-row-ctrl">{children}</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const SettingSection: React.FC<{ title: string; children: React.ReactNode }> = ({
|
||||
title, children,
|
||||
}) => (
|
||||
<div className="stg-section">
|
||||
<div className="stg-section-title">{title}</div>
|
||||
<div className="stg-section-body">{children}</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const TrendSearchSettingsPanel: React.FC<Props> = ({ settings, onChange }) => {
|
||||
const patch = (p: Partial<TrendSearchAppSettings>) => onChange({ ...settings, ...p });
|
||||
|
||||
const weights = useMemo(() => ({
|
||||
weightMaAlignment: settings.weightMaAlignment,
|
||||
weightMaSlope: settings.weightMaSlope,
|
||||
weightAdxTrend: settings.weightAdxTrend,
|
||||
weightMacdMomentum: settings.weightMacdMomentum,
|
||||
weightPricePosition: settings.weightPricePosition,
|
||||
}), [settings]);
|
||||
|
||||
return (
|
||||
<div className="tsd-settings-panel">
|
||||
<SettingSection title="상승추세 검색그룹 배점">
|
||||
<TrendSearchBullishWeightsSection
|
||||
variant="settings"
|
||||
weights={weights}
|
||||
onChange={w => patch(w)}
|
||||
/>
|
||||
</SettingSection>
|
||||
|
||||
<SettingSection title="검색 조건">
|
||||
<SettingRow label="최소 합격 점수" desc="이 점수 이상인 종목만 결과에 포함됩니다.">
|
||||
<input
|
||||
type="number"
|
||||
className="stg-input stg-input--num"
|
||||
min={0}
|
||||
max={100}
|
||||
step={5}
|
||||
value={settings.minTrendScore}
|
||||
onChange={e => patch({ minTrendScore: Number(e.target.value) })}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow label="결과 목록 최대 개수" desc="스캔 후 화면에 표시할 최대 종목 수입니다.">
|
||||
<input
|
||||
type="number"
|
||||
className="stg-input stg-input--num"
|
||||
min={5}
|
||||
max={50}
|
||||
value={settings.limit}
|
||||
onChange={e => patch({ limit: Number(e.target.value) })}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow label="스캔 대상 종목 수" desc="거래대금 상위 N종목을 평가합니다.">
|
||||
<input
|
||||
type="number"
|
||||
className="stg-input stg-input--num"
|
||||
min={20}
|
||||
max={120}
|
||||
value={settings.scanLimit}
|
||||
onChange={e => patch({ scanLimit: Number(e.target.value) })}
|
||||
/>
|
||||
</SettingRow>
|
||||
</SettingSection>
|
||||
|
||||
<SettingSection title="자동 갱신">
|
||||
<SettingRow label="기본 갱신 간격" desc="추세검색 화면 자동 갱신 드롭다운의 기본값입니다.">
|
||||
<select
|
||||
className="stg-select"
|
||||
value={settings.autoRefreshSeconds}
|
||||
onChange={e => patch({ autoRefreshSeconds: Number(e.target.value) })}
|
||||
>
|
||||
{TREND_SEARCH_REFRESH_OPTIONS.map(sec => (
|
||||
<option key={sec} value={sec}>{formatTrendRefreshLabel(sec)}</option>
|
||||
))}
|
||||
</select>
|
||||
</SettingRow>
|
||||
</SettingSection>
|
||||
|
||||
<SettingSection title="투자대상 자동추가">
|
||||
<SettingRow
|
||||
label="자동추가 사용"
|
||||
desc="추세검색 갱신 후 상위 순위 종목을 가상매매 투자대상에 자동 등록합니다."
|
||||
>
|
||||
<label className="stg-toggle">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={settings.autoAddTargetsEnabled}
|
||||
onChange={e => patch({ autoAddTargetsEnabled: e.target.checked })}
|
||||
/>
|
||||
<span className="stg-toggle-slider" />
|
||||
</label>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
label="자동추가 순위 (상위 N위)"
|
||||
desc="추세점수 순위 1위부터 N위까지 자동추가 후보입니다. 투자대상 최대 개수를 초과하면 추가하지 않습니다."
|
||||
>
|
||||
<input
|
||||
type="number"
|
||||
className="stg-input stg-input--num"
|
||||
min={1}
|
||||
max={50}
|
||||
disabled={!settings.autoAddTargetsEnabled}
|
||||
value={settings.autoAddTopRank}
|
||||
onChange={e => patch({ autoAddTopRank: Number(e.target.value) })}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
label="자동추가 최소 점수"
|
||||
desc="상위 순위 안에서도 추세점수가 이 값 이상인 종목만 투자대상에 자동추가합니다."
|
||||
>
|
||||
<input
|
||||
type="number"
|
||||
className="stg-input stg-input--num"
|
||||
min={0}
|
||||
max={100}
|
||||
step={5}
|
||||
disabled={!settings.autoAddTargetsEnabled}
|
||||
value={settings.autoAddMinScore}
|
||||
onChange={e => patch({ autoAddMinScore: Number(e.target.value) })}
|
||||
/>
|
||||
</SettingRow>
|
||||
</SettingSection>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TrendSearchSettingsPanel;
|
||||
Reference in New Issue
Block a user