← back to Ken

react-dash/src/setup/steps/RiskProfile.jsx

110 lines

import React, { useState } from 'react';
import { post } from '../../api';

const PROFILES = [
  {
    name: 'Conservative',
    kelly: 0.05,
    maxBet: 0.25,
    survival: 0.99,
    color: 'blue',
    desc: 'Small bets, maximum safety. Best for learning.',
  },
  {
    name: 'Moderate',
    kelly: 0.10,
    maxBet: 0.50,
    survival: 0.90,
    color: 'purple',
    desc: 'Balanced risk/reward. Recommended for most users.',
    recommended: true,
  },
  {
    name: 'Aggressive',
    kelly: 0.20,
    maxBet: 1.00,
    survival: 0.70,
    color: 'red',
    desc: 'Larger bets, higher variance. For experienced traders.',
  },
];

export default function RiskProfile({ data, update, next, back }) {
  const [selected, setSelected] = useState(data.riskProfile || 'Moderate');
  const [saving, setSaving] = useState(false);

  async function save() {
    setSaving(true);
    const profile = PROFILES.find(p => p.name === selected);
    try {
      await post('/risk', {
        action: 'update_config',
        kelly_fraction: profile.kelly,
        max_bet: profile.maxBet,
        survival_target: profile.survival,
        risk_profile: profile.name,
      });
      update({ riskProfile: selected });
      next();
    } catch {}
    setSaving(false);
  }

  return (
    <div className="space-y-6">
      <div className="text-center">
        <h2 className="text-2xl font-bold mb-2">Risk Profile</h2>
        <p className="text-gray-400 text-sm">Choose how aggressively Poly should trade</p>
      </div>

      <div className="grid grid-cols-3 gap-4">
        {PROFILES.map(p => (
          <button
            key={p.name}
            onClick={() => setSelected(p.name)}
            className={`card text-left transition-all relative ${
              selected === p.name
                ? `ring-2 ring-${p.color === 'blue' ? 'blue' : p.color === 'purple' ? 'purple' : 'red'}-500 bg-${p.color === 'blue' ? 'blue' : p.color === 'purple' ? 'purple' : 'red'}-500/5`
                : 'hover:border-gray-700'
            }`}
            style={selected === p.name ? {
              boxShadow: `0 0 0 2px ${p.color === 'blue' ? '#3b82f6' : p.color === 'purple' ? '#8b5cf6' : '#ef4444'}`,
            } : {}}
          >
            {p.recommended && (
              <span className="absolute -top-2 right-3 text-[9px] font-bold uppercase px-2 py-0.5 rounded-full bg-purple-500 text-white">Recommended</span>
            )}
            <h3 className={`font-bold text-lg mb-1 ${
              p.color === 'blue' ? 'text-blue-400' :
              p.color === 'purple' ? 'text-purple-400' :
              'text-red-400'
            }`}>{p.name}</h3>
            <p className="text-xs text-gray-500 mb-3">{p.desc}</p>
            <div className="space-y-1.5 text-xs">
              <div className="flex justify-between">
                <span className="text-gray-500">Kelly Fraction</span>
                <span className="font-mono text-gray-300">{(p.kelly * 100).toFixed(0)}%</span>
              </div>
              <div className="flex justify-between">
                <span className="text-gray-500">Max Bet</span>
                <span className="font-mono text-gray-300">${p.maxBet.toFixed(2)}</span>
              </div>
              <div className="flex justify-between">
                <span className="text-gray-500">Survival Target</span>
                <span className="font-mono text-gray-300">{(p.survival * 100).toFixed(0)}%</span>
              </div>
            </div>
          </button>
        ))}
      </div>

      <div className="flex items-center justify-between">
        <button onClick={back} className="text-sm text-gray-500 hover:text-gray-300">Back</button>
        <button onClick={save} disabled={saving} className="wizard-btn">
          {saving ? 'Saving...' : 'Save & Continue'}
        </button>
      </div>
    </div>
  );
}