feat: unify NofxOS data provider and fix language consistency

- Add unified NofxOS API key configuration in IndicatorEditor
- Add language field to StrategyConfig for consistent prompt generation
- Auto-update prompt sections when interface language changes
- Remove scattered URL inputs from CoinSourceEditor and IndicatorEditor
- Create nofxos provider package with formatted data output
- Update kernel engine to use config-based language setting
This commit is contained in:
tinkle-community
2026-01-04 00:59:07 +08:00
parent 13fda47151
commit 0275e23b7e
32 changed files with 3029 additions and 1767 deletions

View File

@@ -199,7 +199,7 @@ func (cfg *BacktestConfig) ToStrategyConfig() *store.StrategyConfig {
if len(cfg.Symbols) > 0 {
result.CoinSource.SourceType = "static"
result.CoinSource.StaticCoins = cfg.Symbols
result.CoinSource.UseCoinPool = false
result.CoinSource.UseAI500 = false
result.CoinSource.UseOITop = false
}
@@ -241,12 +241,12 @@ func (cfg *BacktestConfig) ToStrategyConfig() *store.StrategyConfig {
return &store.StrategyConfig{
CoinSource: store.CoinSourceConfig{
SourceType: "static",
StaticCoins: cfg.Symbols,
UseCoinPool: false,
CoinPoolLimit: len(cfg.Symbols),
UseOITop: false,
OITopLimit: 0,
SourceType: "static",
StaticCoins: cfg.Symbols,
UseAI500: false,
AI500Limit: len(cfg.Symbols),
UseOITop: false,
OITopLimit: 0,
},
Indicators: store.IndicatorConfig{
Klines: store.KlineConfig{

View File

@@ -519,7 +519,7 @@ func (r *Runner) buildDecisionContext(ts int64, marketData map[string]*market.Da
// Fetch quantitative data if enabled in strategy (uses current data as approximation)
strategyConfig := r.strategyEngine.GetConfig()
if strategyConfig.Indicators.EnableQuantData && strategyConfig.Indicators.QuantDataAPIURL != "" {
if strategyConfig.Indicators.EnableQuantData {
// Collect symbols to query (candidate coins + position coins)
symbolSet := make(map[string]bool)
for _, sym := range r.cfg.Symbols {
@@ -547,6 +547,24 @@ func (r *Runner) buildDecisionContext(ts int64, marketData map[string]*market.Da
}
}
// Fetch NetFlow ranking data if enabled in strategy
if strategyConfig.Indicators.EnableNetFlowRanking {
ctx.NetFlowRankingData = r.strategyEngine.FetchNetFlowRankingData()
if ctx.NetFlowRankingData != nil {
logger.Infof("💰 Backtest: NetFlow ranking data ready: inst_in=%d, inst_out=%d",
len(ctx.NetFlowRankingData.InstitutionFutureTop), len(ctx.NetFlowRankingData.InstitutionFutureLow))
}
}
// Fetch Price ranking data if enabled in strategy
if strategyConfig.Indicators.EnablePriceRanking {
ctx.PriceRankingData = r.strategyEngine.FetchPriceRankingData()
if ctx.PriceRankingData != nil {
logger.Infof("📈 Backtest: Price ranking data ready for %d durations",
len(ctx.PriceRankingData.Durations))
}
}
record := &store.DecisionRecord{
AccountState: store.AccountSnapshot{
TotalBalance: accountInfo.TotalEquity,