export default {
  common: {
    confirm: 'Confirm',
    cancel: 'Cancel',
    save: 'Save',
    delete: 'Delete',
    edit: 'Edit',
    create: 'Create',
    submit: 'Submit',
    refresh: 'Refresh',
    clear: 'Clear',
    ok: 'OK',
    close: 'Close',
    add: 'Add',
    saved: 'Saved',
    saving: 'Saving',
    deleted: 'Deleted',
    updated: 'Updated',
    added: 'Added',
    success: 'Success',
    failed: 'Failed',
    unknownError: 'Unknown error',
    empty: 'No data',
    optional: 'optional',
    notSet: 'not set',
    none: 'none',
    yes: 'Yes',
    no: 'No',
    actions: 'Actions',
    status: 'Status',
    name: 'Name',
    notes: 'Notes',
    date: 'Date',
    time: 'Time',
    code: 'Code',
    ticker: 'Ticker',
    assetType: 'Asset type',
    stock: 'Stock',
    crypto: 'Crypto',
    detail: 'Detail',
    view: 'View',
    createdAt: 'Created at',
    completedAt: 'Completed at',
    leftEmpty: 'leave blank',
  },

  app: {
    themeRed: 'Theme: red-up / green-down (A-share)',
    themeGreen: 'Theme: green-up / red-down (US)',
    switchLanguage: 'Switch language',
    languageZh: '中文',
    languageEn: 'English',
  },

  menu: {
    dashboard: 'Dashboard',
    analyze: 'New analysis',
    screener: 'Screener',
    holdings: 'Holdings',
    schedule: 'Scheduled',
    paper: 'Paper trading',
    backtest: 'Backtest',
    quality: 'Decision quality',
    history: 'History',
    settings: 'Settings',
  },

  screener: {
    title: 'Screener',
    subtitle: 'Describe your goal in one line — AI screens candidates from the whole market',
    goalPlaceholder: 'e.g. undervalued consumer stocks with main capital inflow',
    useLlm: 'Use AI strategy & rationale (off = pure quantitative factors)',
    topN: 'Results',
    start: 'Screen',
    running: 'Screening…',
    strategy: 'Strategy',
    matched: 'Matched',
    candidates: 'Candidates',
    advanced: 'Advanced filters (optional, overrides AI)',
    peMax: 'PE max',
    pbMax: 'PB max',
    mcMin: 'Mkt cap min (100M)',
    mcMax: 'Mkt cap max (100M)',
    sector: 'Sector/Concept',
    momentumPeriod: 'Momentum period',
    momentumDirection: 'Momentum direction',
    periodToday: 'Today',
    period5d: '1 week (5d)',
    period20d: '1 month (20d)',
    period60d: '60 days',
    periodYtd: 'YTD',
    directionUp: 'Strong ↑ (trend)',
    directionDown: 'Oversold ↓ (rebound)',
    degradedTitle: 'Degraded data source',
    degradedBody: 'Eastmoney is unavailable; switched to {source}. It lacks PE/PB/cap/turnover, so this screen used momentum/capital-flow only and skipped valuation filters. Retry later for full data.',
    history: 'History',
    historyEmpty: 'No history yet',
    reload: 'Load',
    columns: {
      rank: 'Rank',
      name: 'Name',
      price: 'Price',
      changePct: 'Chg%(today)',
      pe: 'PE',
      pb: 'PB',
      marketCap: 'Cap(100M)',
      turnover: 'Turn%',
      score: 'Score',
      reason: 'AI rationale',
    },
    factorBreakdown: 'Factor breakdown',
    value: 'Value',
    momentum: 'Momentum',
    capitalFlow: 'Capital flow',
    risk: 'Risk',
    reasonSourceLlm: 'AI',
    reasonSourceRule: 'Rule',
    selected: '{n} selected',
    addToPaper: 'Add to paper trading',
    batchAnalyze: 'Batch deep analysis',
    sizingTitle: 'Position sizing',
    sizingEqualCash: 'Split cash equally',
    sizingFixedCash: 'Fixed cash each',
    sizingFixedShares: 'Fixed shares each',
    sizingEqualCashHint: 'Fraction of account cash (0-1), split across selected stocks',
    sizingFixedCashHint: 'CNY invested per stock',
    sizingFixedSharesHint: 'Shares bought per stock (A-share rounded to 100-lots)',
    confirmBuy: 'Confirm buy',
    toPaperDone: 'Filled {filled}/{total} orders — view in paper trading',
    toAnalyzeDone: 'Started {n} deep analyses',
    goPaper: 'View paper trading',
    emptySelect: 'Select stocks first',
    noData: 'No candidates yet — run a screen first',
    dataSource: 'Source',
  },

  dashboard: {
    title: 'Dashboard',
    subtitle: 'System overview',
    sysStatus: 'System status',
    apiConnected: 'API connected',
    quickNew: '+ New analysis',
    recent: 'Recent analyses',
    noRecent: 'No analyses yet',
    signalDist: 'Signal distribution',
  },

  analyze: {
    title: 'New analysis',
    subtitle: 'Configure and start a trading analysis',
    smartParse: 'Smart parse',
    smartParsePlaceholder: 'e.g. "Moutai short-term" / "CATL mid-term" / "600519 long-term" / "AAPL 30 days"',
    runParse: 'Parse & fill',
    useLlmFallback: 'Use LLM fallback when rules fail',
    parseHint: 'On success the form is filled below — you can still tweak it before starting.',
    confidence: 'Confidence',
    parseSuccessTip: 'Form filled',
    parseEmpty: 'No ticker recognized — enter manually or enable the LLM fallback and retry.',
    parseFailPrefix: 'Parse failed: ',
    parseFailedTitle: 'Parse failed: no ticker recognized',
    parsedAs: 'Parsed as: ',
    tickerPlaceholder: 'e.g. AAPL, 300750.SZ, 600519.SS, 0700.HK',
    tradeDate: 'Analysis date',
    analystTeam: 'Analyst team',
    analysts: {
      market: 'Technical',
      marketDesc: 'Candles / SMA / MACD / RSI / Bollinger and other indicators (max 8 picked).',
      social: 'Overseas sentiment',
      socialDesc: 'US sentiment: Yahoo news + StockTwits + Reddit (wsb / stocks / investing).',
      news: 'News',
      newsDesc: 'Per-ticker news + global macro news.',
      fundamentals: 'Fundamentals',
      fundamentalsDesc: 'Financials: balance sheet / cash flow / income statement / insider trades.',
      cnSocial: 'A-share sentiment',
      cnSocialDesc: 'A-share sentiment: Eastmoney 股吧 + Weibo / Xiaohongshu / Douyin (Chinese sentiment + 打板/龙头 jargon).',
      event: 'Event-driven',
      eventDesc: 'Reason from news to a causal chain: event → direct impact → supply chain → sector sentiment.',
      capitalFlow: 'Capital flow',
      capitalFlowDesc: 'A-share fund flow: main net inflow / northbound / margin / dragon-tiger list.',
      macro: 'Macro',
      macroDesc: 'CN/US macro indicators: CPI / PPI / M2 / PMI / LPR / USD/CNY / US 10y treasury.',
    },
    analystHint: 'Defaults auto-selected for {cls}; tweak as needed.',
    tickerClass: { cn: 'A-share', us: 'US', hk: 'HK', crypto: 'Crypto', unknown: 'general' },
    debateDepth: 'Research depth',
    debateMarks: { fast: 'Fast', standard: 'Standard', deep: 'Deep' },
    riskRounds: 'Risk rounds',
    provider: 'LLM provider',
    providerPlaceholder: 'Use default',
    deepModel: 'Deep-think model',
    deepModelPlaceholder: 'Use default / pick Deep-think model',
    quickModel: 'Quick-think model',
    quickModelPlaceholder: 'Use default / pick Quick-think model',
    defaultPlaceholder: 'Use default',
    outputLanguage: 'Output language',
    checkpoint: 'Checkpoint',
    startAnalysis: 'Start analysis',
  },

  progress: {
    title: 'Analysis in progress',
    agents: 'Agent status',
    waitingStart: 'Waiting to start...',
    stats: 'Stats',
    events: 'Events',
    debateTurns: 'Debate turns',
    elapsed: 'Elapsed',
    liveDebate: 'Live debate',
    waitingDebate: 'Debate has not started yet...',
    waitingBullBear: 'Waiting for Bull / Bear to enter the debate...',
    liveOutput: 'Live output',
    finalDecision: 'Final decision',
    viewReport: 'View full report',
    analysisCompleted: 'Analysis complete',
    analysisFailed: 'Analysis failed',
  },

  history: {
    title: 'History',
    subtitle: 'All past analyses',
    newAnalysis: '+ New analysis',
    tickerPlaceholder: 'Ticker',
    signal: 'Signal',
    dateFrom: 'From',
    dateTo: 'To',
    cols: {
      ticker: 'Ticker',
      date: 'Date',
      signal: 'Signal',
      confidence: 'Conf.',
      createdAt: 'Created at',
      actions: 'Actions',
    },
    detail: 'Detail',
    delete: 'Delete',
    confirmDeleteTitle: 'Confirm delete',
    confirmDeleteContent: 'This cannot be undone.',
  },

  holdings: {
    title: 'Holdings',
    subtitle: 'Positions / cost / P&L / latest signal',
    addToSchedule: 'Add to scheduled',
    importCsv: 'Import CSV',
    addHolding: 'Add holding',
    stat: {
      count: 'Holdings',
      marketValue: 'Total market value',
      cumulativePnl: 'Cumulative P&L',
      avgPnlPct: 'Avg P&L %',
    },
    empty: 'No holdings yet — click "Add holding" to get started.',
    editTitle: 'Edit holding',
    addTitle: 'Add holding',
    fields: {
      ticker: 'Ticker',
      tickerPlaceholder: 'e.g. 600519 / AAPL / 0700.HK',
      assetType: 'Asset type',
      shares: 'Shares',
      costPrice: 'Cost price',
      openDate: 'Open date',
      notes: 'Notes',
    },
    schedule: {
      title: 'Add holdings to scheduled analysis',
      info: 'Creates a scheduled task per holding; tickers that already have a task are skipped. Tasks can be edited or disabled on the "Scheduled" page.',
      type: 'Trigger',
      daily: 'Daily',
      weekly: 'Weekly',
      interval: 'Interval',
      intervalMinutes: 'Interval (min)',
      timeOfDay: 'Time of day',
      dayOfWeek: 'Day of week',
      enableAnalysts: 'Analysts',
      analystMarket: 'Market',
      analystNews: 'News',
      analystFundamentals: 'Fundamentals',
      analystCnSocial: 'CN sentiment',
      analystEvent: 'Event',
      analystSocial: 'Sentiment',
      createBtn: 'Create',
      createdNew: 'Created {n} scheduled task(s) from holdings.',
      createdMixed: 'Created {created}, skipped {skipped} already-existing.',
      createFailed: 'Create failed: ',
    },
    klineTitle: 'K-line — {ticker}',
    csv: {
      title: 'Bulk import holdings',
      info: 'Paste CSV. Both Chinese (代码/股数/成本价/持仓日期/备注) and English (ticker/shares/cost_price/open_date/notes) headers are accepted.',
      placeholder: 'ticker,shares,cost_price,open_date,notes\n600519,100,1500,2024-01-15,Core holding',
      submit: 'Import',
      okMsg: 'Imported {n} row(s).',
      partialMsg: 'Imported {created}, skipped {skipped}.',
      failed: 'Import failed: ',
    },
    cols: {
      ticker: 'Ticker',
      sharesCost: 'Shares × Cost',
      last: 'Last',
      marketValue: 'Mkt value',
      pnl: 'P&L',
      latestSignal: 'Latest signal',
      openDate: 'Open date',
      notes: 'Notes',
      actions: 'Actions',
    },
    btn: {
      analyze: 'Analyze',
      kline: 'K-line',
      edit: 'Edit',
      delete: 'Delete',
    },
    confirmDeleteTitle: 'Delete holding',
    confirmDeleteContent: 'Delete {ticker}? Past analyses are not affected.',
    saveValidation: 'Please fill ticker, shares and cost price.',
    saveFailed: 'Save failed: ',
  },

  schedule: {
    title: 'Scheduled analyses',
    subtitle: 'Run analyses automatically on a schedule; auto-disable after 3 consecutive failures',
    newTask: 'New task',
    info: 'Times are server-local. Each fired task creates a new analysis; results appear under "History" and "Holdings". Tasks failing 3 times in a row are disabled automatically.',
    empty: 'No scheduled tasks. Click "New task" or use the bulk-add button on the Holdings page.',
    editTitle: 'Edit task',
    createTitle: 'New task',
    fields: {
      name: 'Name',
      namePlaceholder: 'Optional; defaults to ticker',
      tickerPlaceholder: 'e.g. 600519 / AAPL / 0700.HK',
      assetType: 'Asset type',
      triggerType: 'Trigger',
      intervalMinutes: 'Interval (min)',
      intervalPlaceholder: '≥5',
      timeOfDay: 'Time of day',
      dayOfWeek: 'Day of week',
      dowPlaceholder: 'Pick a day',
      enableAnalysts: 'Analysts',
      debateRounds: 'Debate rounds',
      researchDebate: 'Research debate',
      riskDebate: 'Risk debate',
    },
    triggerTypes: { interval: 'Interval', daily: 'Daily', weekly: 'Weekly' },
    days: { mon: 'Mon', tue: 'Tue', wed: 'Wed', thu: 'Thu', fri: 'Fri', sat: 'Sat', sun: 'Sun' },
    status: { active: 'Active', paused: 'Paused', disabled: 'Disabled' },
    pattern: {
      interval: 'Every {n} min',
      daily: 'Daily at {time}',
      weekly: 'Weekly on {dow} at {time}',
    },
    failCount: 'Failed {n}',
    cols: {
      name: 'Name',
      ticker: 'Ticker',
      trigger: 'Trigger',
      analysts: 'Analysts',
      status: 'Status',
      nextRun: 'Next run',
      lastRun: 'Last run',
      actions: 'Actions',
    },
    btn: {
      runNow: 'Run now',
      viewLatest: 'View latest',
      pause: 'Pause',
      enable: 'Enable',
      delete: 'Delete',
    },
    validation: {
      ticker: 'Please enter a ticker',
      intervalMin: 'Interval must be ≥ 5 minutes',
      timeOfDay: 'Please pick a time of day',
    },
    msg: {
      created: 'Task created',
      saveFailed: 'Save failed: ',
      started: 'Triggered',
      triggerFailed: 'Trigger failed: ',
      enabled: 'Enabled',
      paused: 'Paused',
      actionFailed: 'Action failed: ',
    },
    confirmDeleteTitle: 'Delete task',
    confirmDeleteContent: 'Delete scheduled task for {name}? Already-generated analyses are not affected.',
  },

  paper: {
    title: 'Paper trading',
    subtitle: 'Virtual account / one-click order from decisions / NAV curve',
    snapshotBtn: 'Snapshot NAV',
    manualOrder: 'Manual order',
    resetAccount: 'Reset account',
    warning: 'Paper trading is for evaluating "what if we acted on the agent\'s decisions" — orders fill instantly at the specified price, with no slippage/fees/price-limits modeled. Any inferred P&L is NOT investment advice.',
    stats: {
      cash: 'Cash',
      positionsValue: 'Positions value',
      totalValue: 'Total value',
      vsInitial: 'vs initial {n}',
    },
    tabs: {
      positions: 'Positions',
      orders: 'Orders',
      nav: 'NAV curve',
    },
    noPositions: 'No positions',
    noOrders: 'No orders',
    noNav: 'No NAV snapshots yet. Click "Snapshot NAV" to record the first one.',
    klineTitle: 'K-line — {ticker}',
    sellTitle: 'Sell {ticker}',
    sellAShareWarning: 'A-share T+1 rule: **shares bought today cannot be sold today** — only on the next trading day. If you bought today, the backend will reject the sell.',
    sellFields: {
      current: 'Current',
      currentDesc: '{shares} shares × cost {cost}',
      sellShares: 'Sell shares',
      price: 'Price',
      pricePlaceholder: 'Leave blank to use latest close',
      estimated: 'Estimated amount: {amount}',
      empty: '',
      confirm: 'Confirm sell',
    },
    sellValidation: {
      shares: 'Please enter share count',
      notEnough: 'Insufficient shares: max sell {max}',
    },
    msg: {
      sold: 'Sold',
      sellFailed: 'Sell failed: ',
      flattened: 'Flattened {ticker}',
      flattenFailed: 'Flatten failed: ',
      placed: 'Order filled',
      placeFailed: 'Order failed: ',
      snapshotted: 'NAV snapshot recorded',
      snapshotFailed: 'Snapshot failed: ',
      reset: 'Account reset',
      resetFailed: 'Reset failed: ',
    },
    flattenTitle: 'Flatten position',
    flattenContent: 'Sell all {shares} shares of {ticker} at current price?',
    flattenConfirm: 'Confirm flatten',
    flattenNotes: 'Flatten',
    sellNote: 'Manual sell',
    manualOrderTitle: 'Manual order',
    orderFields: {
      ticker: 'Ticker',
      tickerPlaceholder: 'e.g. 600519 / AAPL',
      action: 'Action',
      buy: 'Buy',
      sell: 'Sell',
      shares: 'Shares',
      price: 'Price',
      pricePlaceholder: 'Leave blank to use latest close',
      notes: 'Notes',
    },
    orderValidation: 'Please fill ticker and share count',
    resetTitle: 'Reset account',
    resetContent: 'Clears all positions, orders and NAV snapshots, and restores cash to the initial amount. This cannot be undone.',
    resetConfirm: 'Confirm reset',
    posCols: {
      ticker: 'Ticker',
      sharesCost: 'Shares × Cost',
      last: 'Last',
      marketValue: 'Mkt value',
      pnl: 'P&L',
      actions: 'Actions',
    },
    posBtn: {
      sell: 'Sell',
      flatten: 'Flatten',
      kline: 'K-line',
    },
    orderCols: {
      time: 'Time',
      ticker: 'Ticker',
      action: 'Action',
      shares: 'Shares',
      price: 'Price',
      amount: 'Amount',
      source: 'Source',
      notes: 'Notes',
    },
    source: {
      decision: 'From decision',
      manual: 'Manual',
    },
    navChart: {
      total: 'Total value',
      initial: 'Initial cash',
    },
  },

  backtest: {
    title: 'Backtest',
    subtitle: 'Decision replay · NAV curve · Sharpe / max drawdown / win rate',
    newBtn: 'New backtest',
    intro: {
      header: 'What is "Decision Replay"?',
      principleLabel: 'How it works:',
      principle: 'For every agent analysis you have already run, replay it in chronological order as a virtual order — if the agent said BUY on day X, the engine fills at the real historical price next morning; SELL closes the position. Then compare the simulated NAV against a benchmark to see how good the agent\'s calls actually were.',
      whyLabel: 'Why this way?',
      why: 'Classical backtests re-invoke the agent on historical dates — but the agent doesn\'t see the news/sentiment that existed back then, it sees "today\'s view of that time", which produces',
      whyEmph: 'look-ahead leakage',
      whySuffix: ' (look-ahead bias). Decision replay uses only the decisions actually produced at the time, in strict chronological order, with no leakage.',
      howLabel: 'How to start:',
      how: 'Run a few analyses on the "New analysis" or "Scheduled" page first, generate some BUY/SELL decisions, then come back here.',
      holdEmph: 'HOLD decisions do not place orders',
      howSuffix: ' — if every past analysis was HOLD, the curve will be a flat 1M line.',
      cards: {
        liveBadge: 'Live',
        liveTitle: 'Decision replay',
        liveDesc: 'Replay existing agent decisions; zero LLM cost; strictly leakage-free. Answers "how good was the agent?".',
        planBadge: 'Planned',
        planTitle: 'Rule backtest',
        planDesc: 'MA / MACD / RSI / breakout rules as a baseline against the agent. Phase 2.',
        rerunBadge: 'Evaluating',
        rerunTitle: 'Agent re-run',
        rerunDesc: 'Re-invoke the agent on historical dates. High cost + leakage risk; may never ship.',
      },
    },
    disclaimer: 'Backtests only replay existing agent decisions. Fills are instantaneous and ignore micro-structure beyond a simple fee/slippage model. Results are NOT investment advice; past performance is not indicative of future returns.',
    tabs: { list: 'Runs', detail: 'Detail · {name}' },
    empty: 'No backtests yet. Click "New backtest" to start.',
    createTitle: 'New backtest',
    fields: {
      name: 'Name',
      namePlaceholder: 'Optional; auto-generated from date range',
      dateRange: 'Date range',
      source: 'Signal source',
      universe: 'Universe filter',
      universePlaceholder: 'Leave empty = all tickers found in the decision log',
      benchmark: 'Benchmark',
      benchmarkPlaceholder: 'e.g. 000300.SH (CSI 300) / SPY (US)',
      initialCash: 'Initial cash',
      sizingMode: 'Sizing mode',
      equalWeight: 'Equal weight',
      fixedCash: 'Fixed cash',
      signalStrength: 'By confidence',
      fixedCashPerSignal: 'Cash per signal',
      fixedCashPlaceholder: 'Leave empty = 10% of initial cash',
      confidenceFloor: 'Confidence floor',
      confidenceMarks: { none: 'No filter', med: '≥0.5', high: '≥0.8' },
    },
    sources: {
      memoryLog: 'Agent decision log',
      rule: 'Rule strategy',
      liveAgent: 'Live agent',
    },
    cols: {
      name: 'Name',
      source: 'Source',
      range: 'Range',
      status: 'Status',
      totalReturn: 'Total return',
      benchmark: 'Benchmark',
      mdd: 'Max DD',
      sharpe: 'Sharpe',
      winRate: 'Win rate',
      actions: 'Actions',
    },
    btn: {
      view: 'View',
      delete: 'Delete',
      run: 'Run backtest',
    },
    statusMap: {
      complete: 'Done',
      running: 'Running',
      pending: 'Pending',
      failed: 'Failed',
    },
    validation: {
      dateRange: 'Please pick a date range',
    },
    msg: {
      done: 'Backtest complete',
      failed: 'Backtest failed: ',
    },
    confirmDeleteTitle: 'Delete backtest',
    confirmDeleteContent: 'Delete "{name}"? All its data (NAV / orders / metrics) will be removed.',
  },

  backtestDetail: {
    metrics: {
      totalReturn: 'Total return',
      annualised: 'Annualised return',
      vsBench: 'vs benchmark',
      benchSuffix: 'benchmark {v}',
      mdd: 'Max drawdown',
      sharpe: 'Sharpe',
      sortino: 'Sortino',
      winRate: 'Win rate',
      roundTrips: '{n} round trips',
      profitFactor: 'Profit factor',
      avgWinLoss: 'avg win {win} / loss {loss}',
    },
    navTitle: 'NAV curve',
    navEmpty: 'No NAV snapshots produced for this backtest',
    tradesTitle: 'Trades',
    noTradesAlert: 'Within this backtest\'s window there are no',
    noTradesAlertEmph: 'BUY or SELL',
    noTradesAlertSuffix: ' signals — so no virtual orders were placed and the NAV stays at the initial cash. Common reasons:',
    noTradesReasons: {
      r1: 'All past agent decisions were HOLD (decision replay only orders on BUY/SELL).',
      r2: 'The "Universe filter" doesn\'t match any ticker with signals — try clearing it.',
      r3: 'No analyses ran in this date range — go to "New analysis" or "Scheduled" first.',
    },
    warningsTitle: 'Warnings',
    chart: {
      strategy: 'Strategy NAV',
      benchmark: 'Benchmark {b}',
    },
    cols: {
      date: 'Date',
      ticker: 'Ticker',
      action: 'Action',
      shares: 'Shares',
      price: 'Price',
      fee: 'Fee',
      realisedPnl: 'Realised P&L',
      relatedAnalysis: 'Related analysis',
    },
    actions: { buy: 'Buy', sell: 'Sell' },
  },

  report: {
    titlePrefix: 'Report: {ticker}',
    exportMd: 'Export Markdown',
    paperOrderBtn: 'Paper-order from this',
    reAnalyze: 'Re-analyze',
    summary: {
      ticker: 'Ticker',
      date: 'Date',
      signal: 'Signal',
      confidence: 'Confidence',
      status: 'Status',
      createdAt: 'Created at',
      completedAt: 'Completed at',
      assetType: 'Asset type',
    },
    investDebateEmpty: 'This analysis did not enable / produce a research debate.',
    riskDebateEmpty: 'This analysis did not enable / produce a risk debate.',
    noReports: 'No report data',
    timelineTitle: 'Timeline',
    tabs: {
      macro: 'Macro',
      market: 'Market',
      sentiment: 'Sentiment',
      cnSentiment: 'CN sentiment',
      news: 'News',
      fundamentals: 'Fundamentals',
      capitalFlow: 'Capital flow',
      event: 'Event impact',
      investDebate: 'Research debate',
      researchPlan: 'Research plan',
      traderProposal: 'Trader proposal',
      riskDebate: 'Risk debate',
      finalDecision: 'Final decision',
    },
    paperOrder: {
      title: 'Paper-order from this decision',
      warning: 'Places a paper order using this analysis\'s action + entry price. For drill purposes only — NOT investment advice.',
      mode: 'Mode',
      modeShares: 'By shares',
      modeFraction: 'By cash fraction',
      shares: 'Shares',
      fraction: 'Fraction of cash',
      fractionMarks: { q: '25%', h: '50%', f: 'all in' },
      priceOverride: 'Price override',
      priceOverridePlaceholder: 'Leave empty to use the entry price from the decision',
      validation: 'Please enter share count',
      placed: 'Order placed: {action} {shares} @ {price}',
      buy: 'BUY',
      sell: 'SELL',
      failed: 'Order failed: ',
    },
  },

  settings: {
    title: 'Settings',
    subtitle: 'System configuration',
    llmCard: 'LLM',
    provider: 'Provider',
    deepModel: 'Deep-think model',
    deepPlaceholder: 'Pick a Deep-think model',
    quickModel: 'Quick-think model',
    quickPlaceholder: 'Pick a Quick-think model',
    apiKeysCard: 'API keys',
    apiKeysHeaderExtra: 'Saved to project-root',
    apiKeysHeaderSuffix: '; shared by CLI and Web.',
    apiKeysInfo: 'Fill in the key for whichever provider you want to update, then save. Leaving a field blank does NOT clear an existing key — use the row-end "Clear" button for that.',
    keyNoNeed: 'no key',
    keySet: 'set',
    keyUnset: 'not set',
    placeholderNoNeed: 'This provider does not require an API key.',
    placeholderSet: 'Set ({masked}); type to overwrite',
    placeholderUnset: 'Not set; type to fill',
    clearKey: 'Clear',
    saveKeys: 'Save API keys',
    keyMsg: {
      nothing: 'Nothing to save.',
      updated: 'Updated: {names}',
      updatedNone: 'none',
      saveFailed: 'Save failed: ',
      cleared: 'Cleared {provider}',
      clearFailed: 'Clear failed: ',
    },
    debateCard: 'Debate parameters',
    maxDebateRounds: 'Max debate rounds',
    maxRiskRounds: 'Max risk rounds',
    miscCard: 'Other',
    outputLanguage: 'Output language',
    checkpoint: 'Checkpoint',
    benchmarkTicker: 'Benchmark ticker',
    benchmarkPlaceholder: 'Leave empty for auto-detect',
    dirCard: 'Data dirs (read-only)',
    dirCache: 'Cache dir',
    dirResults: 'Results dir',
    dirMemory: 'Memory log',
    saveBtn: 'Save settings',
    saved: 'Settings saved',
  },

  debate: {
    empty: 'No debate content',
    round: 'Round {n}',
    justArrived: 'Just arrived',
    rawTitle: 'View raw debate text',
    roles: {
      bull: 'Bull',
      bear: 'Bear',
      aggressive: 'Aggressive',
      conservative: 'Conservative',
      neutral: 'Neutral',
    },
  },

  event: {
    empty: 'No event report',
    eventsTitle: 'Key events · causal chains',
    fallbackEventName: 'Event {n}',
    confidence: 'Confidence: {v}',
    directlyRelated: 'Directly related: ',
    stockMatrix: 'Stock impact matrix',
    sectorMatrix: 'Sector impact',
    sectorStrength: 'Strength: {v}',
    indexMatrix: 'Index impact',
    riskTitle: 'A-share trading risks',
    conclusionTitle: 'Conclusion',
    rawTitle: 'View raw Markdown',
  },

  causal: {
    tiers: { event: 'Event', direct: 'Direct impact', supply: 'Supply chain', sector: 'Sector sentiment', followup: 'Follow-up' },
    fallback: 'Impact',
  },

  model: {
    selectPlaceholder: 'Pick a model',
    customPlaceholder: 'Enter a custom model ID',
    freeTextPlaceholder: 'Enter a model ID',
  },

  kline: {
    daily: 'D',
    days30: '30d',
    days60: '60d',
    days120: '120d',
    year1: '1y',
    autoRefresh: 'Auto refresh',
    manualRefresh: 'Manual',
    refresh: 'Refresh',
    fullscreen: 'Fullscreen',
    exitFullscreen: 'Exit fullscreen',
    minuteHint: 'A-share minute bars · AKShare · ~30-60s delay · auto-refresh every 30s',
    dailyHint: 'Daily · refreshes live price during session / stops after close',
    latestBar: 'latest bar: {label}',
    noData: 'No data',
    loadFailed: 'Load failed',
  },

  quality: {
    title: 'Decision quality',
    subtitle: 'Replay every Agent decision against real prices — how good are the calls?',
    empty: 'No completed analyses yet. Run a few from “New analysis” or “Scheduled” so the dashboard has something to score.',
    horizon: {
      d5: '5d',
      d30: '30d',
      d60: '60d',
    },
    intro: {
      header: 'What is “decision quality”?',
      whatLabel: 'What it does: ',
      what: 'For every completed analysis, take the close on the analysis date and the close N trading days later from the same vendor the agents used. Compute the realised return, subtract the regional benchmark return over the same window, and you get alpha. Positive alpha = the agent beat the index over that horizon; negative = it lost to the index.',
      howLabel: 'How to read this page: ',
      how: 'The top KPI row is overall performance. The calibration chart asks whether high-confidence calls really win more often. The dimension table answers which ticker / analyst combo / LLM model has the best alpha. The heatmap colors each day by the average alpha of decisions made that day.',
      benchHint: 'Benchmarks are auto-picked by market: A-share uses CSI 300 (000300.SS), HK uses HSI, US uses SPY, Japan uses N225, etc. HOLD decisions are listed but not counted in win-rate (no implied position).',
    },
    kpi: {
      totalDecisions: 'Total decisions',
      evaluableSuffix: '{n} have completed the N-day window',
      winRate: 'Directional win rate',
      directionalSuffix: 'over {n} directional calls',
      avgAlpha: 'Avg alpha',
      medianSuffix: 'median {v}',
      alphaSharpe: 'Alpha Sharpe',
      sharpeHint: 'per-decision: mean(alpha) / stdev(alpha)',
      avgRaw: 'Avg raw return',
      bestAlpha: 'Best alpha',
      worstAlpha: 'Worst alpha',
      signalCount: 'Signal mix',
    },
    calibration: {
      title: 'Confidence calibration',
      hint: 'A well-calibrated agent has actual win-rate ≈ stated confidence (e.g. confidence 0.8 → ~80% wins). Win-rate well below confidence = overconfident; above = underconfident.',
      actualWinRate: 'Actual win rate',
      ideal: 'Perfect calibration',
      cols: {
        bucket: 'Confidence',
        count: 'N',
        winRate: 'Win rate',
        avgAlpha: 'Avg alpha',
      },
    },
    dim: {
      title: 'Breakdown',
      empty: 'No evaluable samples in this dimension yet',
      ticker: 'By ticker',
      signal: 'By signal',
      analyst: 'By analyst',
      combo: 'By analyst combo',
      llm: 'By LLM',
      cols: {
        key: 'Group',
        total: 'Total',
        evaluable: 'Observed',
        directional: 'Directional',
        winRate: 'Win rate',
        avgAlpha: 'Avg alpha',
        medianAlpha: 'Median alpha',
        sharpe: 'Sharpe',
      },
    },
    heatmap: {
      title: 'Decision calendar heatmap',
      hint: 'Each cell is one day; color = average alpha across that day’s decisions. Red = positive alpha (CN convention), green = negative, grey = no evaluable decisions. Saturation clips at ±10% alpha.',
      cellCount: 'decisions',
      legendNeg: 'more negative ←',
      legendPos: '→ more positive',
    },
    decisions: {
      title: 'All decisions',
      filterTicker: 'Search ticker',
      filterSignal: 'Signal',
      onlyEvaluable: 'Observed only',
      pending: 'Pending',
      win: '✓ Win',
      loss: '✗ Loss',
      openReport: 'Open report',
      cols: {
        tradeDate: 'Trade date',
        ticker: 'Ticker',
        signal: 'Signal',
        confidence: 'Confidence',
        rawReturn: 'N-day return',
        alpha: 'N-day alpha',
        win: 'Result',
        actions: 'Actions',
      },
    },
  },
}
