Add multi-factor conviction gate to activation
Make "qualified" mean an edge candidate, not just R:R + confidence. The gate now also requires (all admin-configurable, defaults on): - high conviction: recommended_action LONG_HIGH / SHORT_HIGH only - clean read: risk_level Low (no contradicting signals) - probable primary target: best target probability >= min (default 60) - Shared predicate: app/services/qualification.py + frontend/src/lib/qualification.ts (mirrored) - Activation config extended (min_target_probability, require_high_conviction, exclude_conflicts) with bool-aware get/update + validation - /trades/performance switched to ?qualified_only=true, applying the full gate server-side; confidence breakdown stays unfiltered - Dashboard "Qualified", Signals "Qualified only" toggle, and Track Record all use the one gate; Admin gains the new controls Sentiment provider runtime config (prior change) included. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import { Section } from '../components/ui/Section';
|
||||
import { SkeletonCard, SkeletonTable } from '../components/ui/Skeleton';
|
||||
import { formatPrice } from '../lib/format';
|
||||
import { recommendationActionLabel } from '../lib/recommendation';
|
||||
import { qualifiesSetup, activationSummary } from '../lib/qualification';
|
||||
import type { TradeSetup } from '../lib/types';
|
||||
|
||||
function fmtR(value: number | null): string {
|
||||
@@ -55,15 +56,12 @@ export default function DashboardPage() {
|
||||
const activation = useActivation();
|
||||
const performance = usePerformance();
|
||||
|
||||
const minRR = activation.data?.min_rr ?? 2;
|
||||
const minConfidence = activation.data?.min_confidence ?? 70;
|
||||
|
||||
const qualifiedSetups = useMemo(
|
||||
() =>
|
||||
(trades.data ?? []).filter(
|
||||
(t) => t.rr_ratio >= minRR && (t.confidence_score ?? 0) >= minConfidence,
|
||||
),
|
||||
[trades.data, minRR, minConfidence],
|
||||
activation.data
|
||||
? (trades.data ?? []).filter((t) => qualifiesSetup(t, activation.data!))
|
||||
: [],
|
||||
[trades.data, activation.data],
|
||||
);
|
||||
|
||||
// Show qualified setups first; fall back to the full list when none qualify
|
||||
@@ -112,7 +110,7 @@ export default function DashboardPage() {
|
||||
<Metric
|
||||
label="Qualified"
|
||||
value={String(qualifiedSetups.length)}
|
||||
sub={`R:R ≥ ${minRR.toFixed(1)} & conf ≥ ${minConfidence.toFixed(0)}%`}
|
||||
sub={activation.data ? activationSummary(activation.data) : 'clears the activation gate'}
|
||||
valueClass={qualifiedSetups.length > 0 ? 'text-blue-300' : 'text-gray-100'}
|
||||
/>
|
||||
<Metric
|
||||
|
||||
Reference in New Issue
Block a user