Files
nofx/kernel/schema.go
tinkle-community 110bf52908 feat: cream terminal redesign, English-only UI, autopilot launch fixes
- Redesign dashboard into a cream-paper + vermilion IBM Plex Mono terminal
  (live L2 order book, cost/liq map, WS K-line, signal matrix, orchestration
  topology, risk radar, execution log, current positions, equity curve)
- Convert all user-facing UI and backend strings/prompts from Chinese to
  English (multi-language retained, default English)
- Add /api/statistics/full endpoint + full-stats frontend wiring
- Fix Autopilot launch: reuse the existing trader instead of creating
  duplicates (eliminates repeat ~35s create cost and stale-trader 404s);
  launch sends 5m scan interval
- Fix unreadable toasts: cream theme with high-contrast text + per-type accent
- Silence background dashboard polls (getTraderConfig) to stop error-toast spam
2026-06-30 16:03:52 +08:00

556 lines
18 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package kernel
// ============================================================================
// Trading Data Schema
// ============================================================================
// Bilingual data dictionary supporting Chinese and English.
// Ensures AI can fully understand data formats regardless of language.
// ============================================================================
const (
SchemaVersion = "1.0.0"
)
// Language represents the language type
type Language string
const (
LangChinese Language = "zh-CN"
LangEnglish Language = "en-US"
)
// ========== Bilingual Field Definitions ==========
// BilingualFieldDef defines a field with bilingual name, formula, and description
type BilingualFieldDef struct {
NameZH string // Chinese name
NameEN string // English name
Unit string // unit of measurement
FormulaZH string // Chinese formula
FormulaEN string // English formula
DescZH string // Chinese description
DescEN string // English description
}
// GetName returns the field name based on language
func (d BilingualFieldDef) GetName(lang Language) string {
if lang == LangChinese {
return d.NameZH
}
return d.NameEN
}
// GetFormula returns the formula based on language
func (d BilingualFieldDef) GetFormula(lang Language) string {
if lang == LangChinese {
return d.FormulaZH
}
return d.FormulaEN
}
// GetDesc returns the description based on language
func (d BilingualFieldDef) GetDesc(lang Language) string {
if lang == LangChinese {
return d.DescZH
}
return d.DescEN
}
// ========== Data Dictionary ==========
// DataDictionary defines the meaning of all fields
var DataDictionary = map[string]map[string]BilingualFieldDef{
"AccountMetrics": {
"Equity": {
NameZH: "Total Equity",
NameEN: "Total Equity",
Unit: "USDT",
FormulaZH: "Available Balance + Unrealized PnL",
FormulaEN: "Available Balance + Unrealized PnL",
DescZH: "Actual net value of the account, including unrealized P&L of all positions",
DescEN: "Actual account value including all unrealized P&L from positions",
},
"Balance": {
NameZH: "Available Balance",
NameEN: "Available Balance",
Unit: "USDT",
FormulaZH: "Initial Capital + Realized PnL",
FormulaEN: "Initial Capital + Realized PnL",
DescZH: "Funds available for opening new positions, excluding used margin",
DescEN: "Available funds for opening new positions, excluding used margin",
},
"PnL": {
NameZH: "Total PnL Percentage",
NameEN: "Total PnL Percentage",
Unit: "%",
FormulaZH: "(Total Equity - Initial Capital) / Initial Capital × 100",
FormulaEN: "(Total Equity - Initial Capital) / Initial Capital × 100",
DescZH: "Total return since system startup, +15.87% means 15.87% profit",
DescEN: "Total return since inception, +15.87% means 15.87% profit",
},
"Margin": {
NameZH: "Margin Usage Rate",
NameEN: "Margin Usage Rate",
Unit: "%",
FormulaZH: "Total Used Margin / Total Equity × 100",
FormulaEN: "Total Used Margin / Total Equity × 100",
DescZH: "The higher this value, the greater the account risk. Safe <30%, Dangerous >70%",
DescEN: "Higher value = higher risk. Safe <30%, Dangerous >70%",
},
},
"TradeMetrics": {
"Entry": {
NameZH: "Entry Price",
NameEN: "Entry Price",
Unit: "USDT",
DescZH: "Average price when opening the position",
DescEN: "Average price when opening position",
},
"Exit": {
NameZH: "Exit Price",
NameEN: "Exit Price",
Unit: "USDT",
DescZH: "Average price when closing the position",
DescEN: "Average price when closing position",
},
"Profit": {
NameZH: "Realized PnL",
NameEN: "Realized PnL",
Unit: "USDT",
FormulaZH: "(Exit Price - Entry Price) / Entry Price × Leverage × Position Value",
FormulaEN: "(Exit Price - Entry Price) / Entry Price × Leverage × Position Value",
DescZH: "Actual P&L of closed trades, including fees. Positive=profit, Negative=loss",
DescEN: "Actual profit/loss of closed trades including fees. Positive=profit, Negative=loss",
},
"PnL%": {
NameZH: "PnL Percentage",
NameEN: "PnL Percentage",
Unit: "%",
FormulaZH: "(Exit - Entry) / Entry × Leverage × 100",
FormulaEN: "(Exit - Entry) / Entry × Leverage × 100",
DescZH: "Return on a closed trade, +6.71% means 6.71% profit",
DescEN: "Return on closed trade, +6.71% means 6.71% profit",
},
"HoldDuration": {
NameZH: "Holding Duration",
NameEN: "Holding Duration",
Unit: "minutes",
DescZH: "Time from open to close. <15min=scalping, 15min-4h=intraday, >4h=swing",
DescEN: "Time from open to close. <15min=scalping, 15min-4h=intraday, >4h=swing",
},
},
"PositionMetrics": {
"UnrealizedPnL%": {
NameZH: "Unrealized PnL Percentage",
NameEN: "Unrealized PnL Percentage",
Unit: "%",
FormulaZH: "(Current Price - Entry Price) / Entry Price × Leverage × 100",
FormulaEN: "(Current Price - Entry Price) / Entry Price × Leverage × 100",
DescZH: "Floating P&L of the current position, fluctuating until closed",
DescEN: "Floating P&L of current position, not realized until closed",
},
"PeakPnL%": {
NameZH: "Peak PnL Percentage",
NameEN: "Peak PnL Percentage",
Unit: "%",
DescZH: "Highest unrealized P&L this position has reached. Used to decide whether to take profit",
DescEN: "Historical max unrealized PnL for this position. Used for take-profit decisions",
},
"Drawdown": {
NameZH: "Drawdown from Peak",
NameEN: "Drawdown from Peak",
Unit: "%",
FormulaZH: "Current PnL% - Peak PnL%",
FormulaEN: "Current PnL% - Peak PnL%",
DescZH: "Negative value means pulling back. E.g., Peak +5%, Current +3%, Drawdown = -2%",
DescEN: "Negative = pulling back. E.g., Peak +5%, Current +3%, Drawdown = -2%",
},
"Leverage": {
NameZH: "Leverage",
NameEN: "Leverage",
Unit: "x",
DescZH: "3x means a 1% price move = 3% position PnL. Higher leverage = higher risk",
DescEN: "3x means 1% price move = 3% position PnL. Higher leverage = higher risk",
},
"Margin": {
NameZH: "Margin Used",
NameEN: "Margin Used",
Unit: "USDT",
FormulaZH: "Position Value / Leverage",
FormulaEN: "Position Value / Leverage",
DescZH: "Amount of margin locked for this position",
DescEN: "Collateral locked for this position",
},
"LiqPrice": {
NameZH: "Liquidation Price",
NameEN: "Liquidation Price",
Unit: "USDT",
DescZH: "Position will be force-closed when price reaches this value. 0.0000 = no liquidation risk",
DescEN: "Price at which position will be force-closed. 0.0000 = no liquidation risk",
},
},
"MarketData": {
"Volume": {
NameZH: "Volume",
NameEN: "Volume",
Unit: "base asset",
DescZH: "Trading volume in this period",
DescEN: "Trading volume in this period",
},
"OI": {
NameZH: "Open Interest",
NameEN: "Open Interest",
Unit: "USDT",
DescZH: "Total value of open contracts. Increasing OI = capital inflow, decreasing = outflow",
DescEN: "Total value of open contracts. Increasing OI = capital inflow, decreasing = outflow",
},
"OIChange": {
NameZH: "OI Change",
NameEN: "OI Change",
Unit: "USDT & %",
DescZH: "OI change within 1 hour. Used to judge the real market capital flow direction",
DescEN: "OI change in 1 hour. Used to determine real capital flow direction",
},
},
}
// ========== Bilingual Rule Definitions ==========
// BilingualRuleDef defines a trading rule with bilingual description and reason
type BilingualRuleDef struct {
Value interface{} // rule value
DescZH string // Chinese description
DescEN string // English description
ReasonZH string // Chinese reason
ReasonEN string // English reason
}
// GetDesc returns the description based on language
func (d BilingualRuleDef) GetDesc(lang Language) string {
if lang == LangChinese {
return d.DescZH
}
return d.DescEN
}
// GetReason returns the reason based on language
func (d BilingualRuleDef) GetReason(lang Language) string {
if lang == LangChinese {
return d.ReasonZH
}
return d.ReasonEN
}
// ========== Trading Rules ==========
// TradingRules defines the trading rules
var TradingRules = struct {
RiskManagement map[string]BilingualRuleDef
EntrySignals map[string]BilingualRuleDef
ExitSignals map[string]BilingualRuleDef
PositionControl map[string]BilingualRuleDef
}{
RiskManagement: map[string]BilingualRuleDef{
"MaxMarginUsage": {
Value: 0.30,
DescZH: "Margin usage must not exceed 30%",
DescEN: "Margin usage must not exceed 30%",
ReasonZH: "Reserve 70% capital for extreme market conditions and margin calls",
ReasonEN: "Reserve 70% capital for extreme market conditions and margin calls",
},
"MaxPositionLoss": {
Value: -0.05,
DescZH: "Must stop-loss when single position loss reaches -5%",
DescEN: "Must stop-loss when single position loss reaches -5%",
ReasonZH: "Prevent excessive loss from single trade",
ReasonEN: "Prevent excessive loss from single trade",
},
"MaxDailyLoss": {
Value: -0.10,
DescZH: "Stop trading when daily loss reaches -10%",
DescEN: "Stop trading when daily loss reaches -10%",
ReasonZH: "Prevent emotional trading leading to consecutive losses",
ReasonEN: "Prevent emotional trading leading to consecutive losses",
},
"PositionSizeLimit": {
Value: 0.15,
DescZH: "Single position must not exceed 15% of total equity",
DescEN: "Single position must not exceed 15% of total equity",
ReasonZH: "Avoid excessive risk concentration",
ReasonEN: "Avoid excessive risk concentration",
},
},
EntrySignals: map[string]BilingualRuleDef{
"VolumeSpike": {
Value: 2.0,
DescZH: "Consider entry when volume is 2x above average",
DescEN: "Consider entry when volume is 2x above average",
ReasonZH: "Volume breakout usually indicates strong trend",
ReasonEN: "Volume breakout usually indicates strong trend",
},
"OIChangeThreshold": {
Value: 0.02,
DescZH: "OI change >2% in 1 hour is considered significant",
DescEN: "OI change >2% in 1 hour is considered significant",
ReasonZH: "Large capital flows cause significant OI changes",
ReasonEN: "Large capital flows cause significant OI changes",
},
},
ExitSignals: map[string]BilingualRuleDef{
"TrailingStop": {
Value: 0.30,
DescZH: "Close position when PnL pulls back 30% from peak",
DescEN: "Close position when PnL pulls back 30% from peak",
ReasonZH: "Lock in most profits, avoid profit giveback. E.g., Peak +5%, close at +3.5%",
ReasonEN: "Lock in most profits, avoid profit giveback. E.g., Peak +5%, close at +3.5%",
},
"StopLoss": {
Value: -0.05,
DescZH: "Hard stop-loss at -5%",
DescEN: "Hard stop-loss at -5%",
ReasonZH: "Strictly control maximum single-trade loss",
ReasonEN: "Strictly control maximum single-trade loss",
},
},
PositionControl: map[string]BilingualRuleDef{
"ScaleIn": {
Value: map[string]interface{}{"enabled": true, "max_additions": 2, "price_requirement": 0.01},
DescZH: "Only add to winning positions, max 2 additions, price must be 1% above avg cost",
DescEN: "Only add to winning positions, max 2 additions, price must be 1% above avg cost",
ReasonZH: "Add to winners, never average down losers",
ReasonEN: "Add to winners, never average down losers",
},
"ScaleOut": {
Value: []map[string]interface{}{
{"pnl": 0.03, "close_pct": 0.33},
{"pnl": 0.05, "close_pct": 0.50},
{"pnl": 0.08, "close_pct": 1.00},
},
DescZH: "Scale-out: Close 33% at +3%, 50% at +5%, 100% at +8%",
DescEN: "Scale-out: Close 33% at +3%, 50% at +5%, 100% at +8%",
ReasonZH: "Lock profits while letting winners run",
ReasonEN: "Lock profits while letting winners run",
},
},
}
// ========== OI Interpretation ==========
// OIInterpretation defines bilingual market interpretations for OI changes
type OIInterpretationType struct {
OIUp_PriceUp struct {
ZH string
EN string
}
OIUp_PriceDown struct {
ZH string
EN string
}
OIDown_PriceUp struct {
ZH string
EN string
}
OIDown_PriceDown struct {
ZH string
EN string
}
}
var OIInterpretation = OIInterpretationType{
OIUp_PriceUp: struct {
ZH string
EN string
}{
ZH: "Strong bullish trend (new longs opening, capital flowing into long positions)",
EN: "Strong bullish trend (new longs opening, capital flowing into long positions)",
},
OIUp_PriceDown: struct {
ZH string
EN string
}{
ZH: "Strong bearish trend (new shorts opening, capital flowing into short positions)",
EN: "Strong bearish trend (new shorts opening, capital flowing into short positions)",
},
OIDown_PriceUp: struct {
ZH string
EN string
}{
ZH: "Shorts covering (shorts stopped out, potential reversal)",
EN: "Shorts covering (shorts stopped out, potential reversal)",
},
OIDown_PriceDown: struct {
ZH string
EN string
}{
ZH: "Longs closing (longs stopped out, potential reversal)",
EN: "Longs closing (longs stopped out, potential reversal)",
},
}
// ========== Common Mistakes ==========
// CommonMistake defines a common mistake with bilingual fields
type CommonMistake struct {
ErrorZH string
ErrorEN string
ExampleZH string
ExampleEN string
CorrectZH string
CorrectEN string
}
var CommonMistakes = []CommonMistake{
{
ErrorZH: "Confusing realized and unrealized P&L",
ErrorEN: "Confusing realized and unrealized P&L",
ExampleZH: "Adding historical trade P&L with current position P&L",
ExampleEN: "Adding historical trade P&L with current position P&L",
CorrectZH: "Realized P&L is already included in account balance, don't double count",
CorrectEN: "Realized P&L is already included in account balance, don't double count",
},
{
ErrorZH: "Ignoring leverage's impact on P&L",
ErrorEN: "Ignoring leverage's impact on P&L",
ExampleZH: "Price up 1%, thinking profit is 1%",
ExampleEN: "Price up 1%, thinking profit is 1%",
CorrectZH: "With 3x leverage, 1% price move = ~3% P&L",
CorrectEN: "With 3x leverage, 1% price move = ~3% P&L",
},
{
ErrorZH: "Not understanding Peak PnL's importance",
ErrorEN: "Not understanding Peak PnL's importance",
ExampleZH: "Only watching current PnL, ignoring drawdown",
ExampleEN: "Only watching current PnL, ignoring drawdown",
CorrectZH: "When current PnL near Peak PnL, consider taking profit to lock in gains",
CorrectEN: "When current PnL near Peak PnL, consider taking profit to lock in gains",
},
{
ErrorZH: "Ignoring Open Interest changes",
ErrorEN: "Ignoring Open Interest changes",
ExampleZH: "Only watching price candles, not capital flows",
ExampleEN: "Only watching price candles, not capital flows",
CorrectZH: "Use OI changes to validate trend authenticity and sustainability",
CorrectEN: "Use OI changes to validate trend authenticity and sustainability",
},
}
// ========== Prompt Generation Functions ==========
// GetSchemaPrompt generates schema description text for AI prompts
func GetSchemaPrompt(lang Language) string {
if lang == LangChinese {
return getSchemaPromptZH()
}
return getSchemaPromptEN()
}
// getSchemaPromptZH generates the Chinese prompt
func getSchemaPromptZH() string {
prompt := "# 📖 Data Dictionary & Trading Rules\n\n"
prompt += "## 📊 Field Definitions\n\n"
// Account metrics
prompt += "### Account Metrics\n"
for key, field := range DataDictionary["AccountMetrics"] {
prompt += formatFieldDefZH(key, field)
}
// Trade metrics
prompt += "\n### Trade Metrics\n"
for key, field := range DataDictionary["TradeMetrics"] {
prompt += formatFieldDefZH(key, field)
}
// Position metrics
prompt += "\n### Position Metrics\n"
for key, field := range DataDictionary["PositionMetrics"] {
prompt += formatFieldDefZH(key, field)
}
// Market data
prompt += "\n### Market Data\n"
for key, field := range DataDictionary["MarketData"] {
prompt += formatFieldDefZH(key, field)
}
// OI interpretation
prompt += "\n## 💹 Open Interest (OI) Change Interpretation\n\n"
prompt += "- **OI Up + Price Up**: " + OIInterpretation.OIUp_PriceUp.ZH + "\n"
prompt += "- **OI Up + Price Down**: " + OIInterpretation.OIUp_PriceDown.ZH + "\n"
prompt += "- **OI Down + Price Up**: " + OIInterpretation.OIDown_PriceUp.ZH + "\n"
prompt += "- **OI Down + Price Down**: " + OIInterpretation.OIDown_PriceDown.ZH + "\n"
return prompt
}
// getSchemaPromptEN generates the English prompt
func getSchemaPromptEN() string {
prompt := "# 📖 Data Dictionary & Trading Rules\n\n"
prompt += "## 📊 Field Definitions\n\n"
// Account Metrics
prompt += "### Account Metrics\n"
for key, field := range DataDictionary["AccountMetrics"] {
prompt += formatFieldDefEN(key, field)
}
// Trade Metrics
prompt += "\n### Trade Metrics\n"
for key, field := range DataDictionary["TradeMetrics"] {
prompt += formatFieldDefEN(key, field)
}
// Position Metrics
prompt += "\n### Position Metrics\n"
for key, field := range DataDictionary["PositionMetrics"] {
prompt += formatFieldDefEN(key, field)
}
// Market Data
prompt += "\n### Market Data\n"
for key, field := range DataDictionary["MarketData"] {
prompt += formatFieldDefEN(key, field)
}
// OI Interpretation
prompt += "\n## 💹 Open Interest (OI) Change Interpretation\n\n"
prompt += "- **OI Up + Price Up**: " + OIInterpretation.OIUp_PriceUp.EN + "\n"
prompt += "- **OI Up + Price Down**: " + OIInterpretation.OIUp_PriceDown.EN + "\n"
prompt += "- **OI Down + Price Up**: " + OIInterpretation.OIDown_PriceUp.EN + "\n"
prompt += "- **OI Down + Price Down**: " + OIInterpretation.OIDown_PriceDown.EN + "\n"
return prompt
}
// formatFieldDefZH formats a field definition in Chinese
func formatFieldDefZH(key string, field BilingualFieldDef) string {
result := "- **" + key + "** (" + field.NameZH + "): " + field.DescZH
if field.FormulaZH != "" {
result += " | Formula: `" + field.FormulaZH + "`"
}
if field.Unit != "" {
result += " | Unit: " + field.Unit
}
result += "\n"
return result
}
// formatFieldDefEN formats a field definition in English
func formatFieldDefEN(key string, field BilingualFieldDef) string {
result := "- **" + key + "** (" + field.NameEN + "): " + field.DescEN
if field.FormulaEN != "" {
result += " | Formula: `" + field.FormulaEN + "`"
}
if field.Unit != "" {
result += " | Unit: " + field.Unit
}
result += "\n"
return result
}