607 lines
26 KiB
Markdown
607 lines
26 KiB
Markdown
# QuantDinger Changelog
|
|
|
|
This document records version updates, new features, bug fixes, and database migration instructions.
|
|
|
|
---
|
|
|
|
## V2.2.1 (2026-02-27)
|
|
|
|
### 🚀 New Features
|
|
|
|
#### Membership & Billing System
|
|
- **Subscription Plans**: Monthly / Yearly / Lifetime tiers with configurable pricing and credit bundles
|
|
- **Credit System**: Each plan includes credits; lifetime members receive recurring monthly credit bonuses
|
|
- **Plan Management**: All plan prices, credits, and bonus amounts configurable via System Settings → Billing Configuration
|
|
- **Membership Orders**: Order tracking with status management (paid / pending / failed / refunded)
|
|
|
|
#### USDT On-Chain Payment (TRC20)
|
|
- **HD Wallet Integration**: Per-order unique receiving address derived from xpub (BIP-32/44) — no private key on server
|
|
- **Automatic Reconciliation**: Background polling via TronGrid API detects incoming payments and confirms orders
|
|
- **Depth-Flexible xpub**: Supports both account-level (depth=3) and change-level (depth=4) xpub keys
|
|
- **Configurable Expiry**: Order expiration time and confirmation delay configurable in System Settings
|
|
- **Scan-to-Pay Modal**: Professional checkout UI with QR code, step indicator, real-time status, copy-to-clipboard, dark theme support
|
|
|
|
#### VIP Free Indicators
|
|
- **VIP Free Tag**: Admins can mark community indicators as "VIP Free" when publishing
|
|
- **Zero-Credit Access**: VIP members can use VIP-free indicators without spending credits
|
|
- **Visual Badge**: VIP Free indicators display a distinct badge in the Indicator Market
|
|
|
|
#### AI Trading Opportunities Radar
|
|
- **Multi-Market Scanning**: Auto-scans Crypto, US Stocks, and Forex markets every hour
|
|
- **Rolling Carousel**: Opportunities displayed in a rotating carousel with market-specific styling
|
|
- **Signal Classification**: BUY / SELL signals with percentage change and reason text
|
|
- **Multi-Language**: All radar card content fully internationalized
|
|
|
|
#### Simplified Strategy Creation
|
|
- **Simple / Advanced Mode Toggle**: New users start with simplified mode, power users can switch to advanced
|
|
- **Smart Defaults**: 15-minute K-line period, 5x leverage, market order, sensible TP/SL percentages
|
|
- **Live Trading Disclaimer**: Mandatory risk acknowledgment checkbox before enabling live trading
|
|
|
|
#### System Settings Simplification
|
|
- **Streamlined Configuration**: Removed redundant config groups (server, strategy); consolidated into essential categories
|
|
- **Market Order Default**: Changed default order mode to market order for reliable execution
|
|
- **Billing Config i18n**: All billing configuration items fully multi-language supported
|
|
|
|
#### Indicator Market Performance Tracking
|
|
- **Live Performance Data**: Fixed aggregation to correctly parse backtest `result_json` and include live trade data
|
|
- **Combined Metrics**: Backtest return, live PnL, and win rate now properly displayed on indicator cards
|
|
|
|
### 🐛 Bug Fixes
|
|
- Fixed "Live Performance" data showing all zeros in Indicator Market (incorrect SQL query referencing non-existent columns)
|
|
- Fixed incorrect entry price display in Position Records (was falling back to current price)
|
|
- Fixed inaccurate System Overview statistics for running strategies, total capital, and total PnL
|
|
- Fixed multiple duplicate i18n key issues in `zh-CN.js` and `en-US.js` causing ESLint build failures
|
|
- Fixed exposed i18n keys (`common.loading`, `common.noData`, `systemOverview.*`) not configured
|
|
- Fixed HTML nesting issues in trading assistant strategy creation form
|
|
- Fixed `ed25519-blake2b` build failure in Docker by adding temporary build dependencies
|
|
- Fixed "Current depth (3) is not suitable for deriving address" error for xpub — now compatible with both depth 3 and depth 4
|
|
|
|
### 🎨 UI/UX Improvements
|
|
- Removed "Total Analyses" / "Accuracy Rate" row from homepage AI Analysis section
|
|
- Removed "Search" and "Portfolio Checkup" features from AI Asset Analysis page
|
|
- Professional USDT checkout modal with custom header, step indicator, dual-column layout
|
|
- Dark theme and mobile responsive support for payment modal
|
|
- Trading Opportunities Radar carousel with smooth scrolling animation
|
|
|
|
### 📋 Database Migration
|
|
|
|
**Run the following SQL on your PostgreSQL database before deploying V2.2.1:**
|
|
|
|
```sql
|
|
-- ============================================================
|
|
-- QuantDinger V2.2.1 Database Migration
|
|
-- Membership, USDT Payment, VIP Free Indicators
|
|
-- ============================================================
|
|
|
|
-- 1. User Table: Add membership columns
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'qd_users' AND column_name = 'vip_plan'
|
|
) THEN
|
|
ALTER TABLE qd_users ADD COLUMN vip_plan VARCHAR(20) DEFAULT '';
|
|
RAISE NOTICE 'Added vip_plan column to qd_users';
|
|
END IF;
|
|
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'qd_users' AND column_name = 'vip_is_lifetime'
|
|
) THEN
|
|
ALTER TABLE qd_users ADD COLUMN vip_is_lifetime BOOLEAN DEFAULT FALSE;
|
|
RAISE NOTICE 'Added vip_is_lifetime column to qd_users';
|
|
END IF;
|
|
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'qd_users' AND column_name = 'vip_monthly_credits_last_grant'
|
|
) THEN
|
|
ALTER TABLE qd_users ADD COLUMN vip_monthly_credits_last_grant TIMESTAMP;
|
|
RAISE NOTICE 'Added vip_monthly_credits_last_grant column to qd_users';
|
|
END IF;
|
|
END $$;
|
|
|
|
-- 2. Indicator Codes: Add VIP Free flag
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'qd_indicator_codes' AND column_name = 'vip_free'
|
|
) THEN
|
|
ALTER TABLE qd_indicator_codes ADD COLUMN vip_free BOOLEAN DEFAULT FALSE;
|
|
RAISE NOTICE 'Added vip_free column to qd_indicator_codes';
|
|
END IF;
|
|
END $$;
|
|
|
|
-- 3. Membership Orders table
|
|
CREATE TABLE IF NOT EXISTS qd_membership_orders (
|
|
id SERIAL PRIMARY KEY,
|
|
user_id INTEGER NOT NULL REFERENCES qd_users(id) ON DELETE CASCADE,
|
|
plan VARCHAR(20) NOT NULL,
|
|
price_usd DECIMAL(10,2) DEFAULT 0,
|
|
status VARCHAR(20) DEFAULT 'paid',
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
paid_at TIMESTAMP
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_membership_orders_user_id ON qd_membership_orders(user_id);
|
|
|
|
-- 4. USDT Orders table (on-chain payment tracking)
|
|
CREATE TABLE IF NOT EXISTS qd_usdt_orders (
|
|
id SERIAL PRIMARY KEY,
|
|
user_id INTEGER NOT NULL REFERENCES qd_users(id) ON DELETE CASCADE,
|
|
plan VARCHAR(20) NOT NULL,
|
|
chain VARCHAR(20) NOT NULL DEFAULT 'TRC20',
|
|
amount_usdt DECIMAL(20,6) NOT NULL DEFAULT 0,
|
|
address_index INTEGER NOT NULL DEFAULT 0,
|
|
address VARCHAR(80) NOT NULL DEFAULT '',
|
|
status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
|
tx_hash VARCHAR(120) DEFAULT '',
|
|
paid_at TIMESTAMP,
|
|
confirmed_at TIMESTAMP,
|
|
expires_at TIMESTAMP,
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|
);
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_usdt_orders_address_unique ON qd_usdt_orders(chain, address);
|
|
CREATE INDEX IF NOT EXISTS idx_usdt_orders_user_id ON qd_usdt_orders(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_usdt_orders_status ON qd_usdt_orders(status);
|
|
|
|
-- Migration Complete
|
|
DO $$
|
|
BEGIN
|
|
RAISE NOTICE '✅ QuantDinger V2.2.1 database migration completed!';
|
|
END $$;
|
|
```
|
|
|
|
**Migration Notes:**
|
|
- All statements use `IF NOT EXISTS` — safe to run multiple times
|
|
- No existing data is modified or deleted
|
|
- New `.env` variables required for USDT payment: `USDT_PAY_ENABLED`, `USDT_TRC20_XPUB`, `TRONGRID_API_KEY`
|
|
- New `.env` variables for membership pricing: `MEMBERSHIP_MONTHLY_PRICE_USD`, `MEMBERSHIP_MONTHLY_CREDITS`, etc.
|
|
- See `backend_api_python/env.example` for all new configuration options
|
|
|
|
### 📝 Configuration Notes
|
|
|
|
New environment variables (all optional, with defaults):
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `MEMBERSHIP_MONTHLY_PRICE_USD` | `19.9` | Monthly plan price |
|
|
| `MEMBERSHIP_MONTHLY_CREDITS` | `500` | Credits included in monthly plan |
|
|
| `MEMBERSHIP_YEARLY_PRICE_USD` | `169` | Yearly plan price |
|
|
| `MEMBERSHIP_YEARLY_CREDITS` | `8000` | Credits included in yearly plan |
|
|
| `MEMBERSHIP_LIFETIME_PRICE_USD` | `499` | Lifetime plan price |
|
|
| `MEMBERSHIP_LIFETIME_CREDITS` | `30000` | Initial credits for lifetime plan |
|
|
| `MEMBERSHIP_LIFETIME_MONTHLY_BONUS` | `500` | Monthly bonus credits for lifetime members |
|
|
| `USDT_PAY_ENABLED` | `false` | Enable USDT TRC20 payment |
|
|
| `USDT_TRC20_XPUB` | _(empty)_ | TRC20 HD wallet xpub for address derivation |
|
|
| `TRONGRID_API_KEY` | _(empty)_ | TronGrid API key for on-chain monitoring |
|
|
| `USDT_ORDER_EXPIRE_MINUTES` | `30` | USDT order expiration time |
|
|
|
|
---
|
|
|
|
## V2.1.3 (2026-02-XX)
|
|
|
|
### 🚀 New Features
|
|
|
|
#### Cross-Sectional Strategy Support
|
|
- **Multi-Symbol Portfolio Management** - Added support for cross-sectional strategies that manage a portfolio of multiple symbols simultaneously
|
|
- Strategy type selection: Single Symbol vs Cross-Sectional
|
|
- Symbol list configuration: Select multiple symbols for portfolio management
|
|
- Portfolio size: Configure the number of symbols to hold simultaneously
|
|
- Long/Short ratio: Set the proportion of long vs short positions (0-1)
|
|
- Rebalance frequency: Daily, Weekly, or Monthly portfolio rebalancing
|
|
- Indicator execution: Indicators receive a `data` dictionary (symbol -> DataFrame) for cross-symbol analysis
|
|
- Signal generation: Automatic buy/sell/close signals based on indicator rankings
|
|
- Parallel execution: Multiple orders executed concurrently for efficiency
|
|
- **Backend Implementation**
|
|
- Cross-sectional configurations stored in `trading_config` JSON field
|
|
- New `_run_cross_sectional_strategy_loop` method in TradingExecutor
|
|
- Automatic rebalancing based on configured frequency
|
|
- Support for both long and short positions in the same portfolio
|
|
- **Frontend UI**
|
|
- Strategy type selector in strategy creation/editing form
|
|
- Conditional display of single-symbol vs cross-sectional configuration fields
|
|
- Multi-select symbol picker for cross-sectional strategies
|
|
- Full i18n support (Chinese and English)
|
|
|
|
See `docs/CROSS_SECTIONAL_STRATEGY_GUIDE_CN.md` or `docs/CROSS_SECTIONAL_STRATEGY_GUIDE_EN.md` for detailed usage instructions.
|
|
|
|
### 🐛 Bug Fixes
|
|
- Fixed decimal precision issues in exchange order quantities (Binance Spot LOT_SIZE filter errors)
|
|
- Improved `_dec_str` method across all exchange clients for accurate quantity formatting
|
|
- Enhanced quantity normalization to respect exchange precision requirements
|
|
- Fixed validation logic for cross-sectional strategies (now validates correct symbol list field)
|
|
- Fixed success message to show correct strategy count for cross-sectional strategies
|
|
|
|
### 📋 Database Migration
|
|
|
|
**Run the following SQL on your PostgreSQL database before deploying V2.1.3:**
|
|
|
|
```sql
|
|
-- ============================================================
|
|
-- QuantDinger V2.1.3 Database Migration
|
|
-- Cross-Sectional Strategy Support
|
|
-- ============================================================
|
|
|
|
-- Add last_rebalance_at column to track rebalancing time for cross-sectional strategies
|
|
-- Note: Cross-sectional strategy configurations (symbol_list, portfolio_size, long_ratio, rebalance_frequency)
|
|
-- are stored in the trading_config JSON field, not as separate database columns.
|
|
-- This migration only adds the last_rebalance_at timestamp field which is needed for rebalancing logic.
|
|
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'qd_strategies_trading'
|
|
AND column_name = 'last_rebalance_at'
|
|
) THEN
|
|
ALTER TABLE qd_strategies_trading
|
|
ADD COLUMN last_rebalance_at TIMESTAMP;
|
|
RAISE NOTICE 'Added last_rebalance_at column to qd_strategies_trading';
|
|
ELSE
|
|
RAISE NOTICE 'Column last_rebalance_at already exists';
|
|
END IF;
|
|
END $$;
|
|
```
|
|
|
|
**Migration Notes:**
|
|
- This migration is safe to run multiple times (uses IF NOT EXISTS check)
|
|
- Cross-sectional strategy configurations are stored in the `trading_config` JSON field, so no additional columns are needed
|
|
- The `last_rebalance_at` field is used to track when the last rebalancing occurred for cross-sectional strategies
|
|
- If you don't run this migration, cross-sectional strategies will still work, but rebalancing frequency checks may not function correctly
|
|
|
|
---
|
|
|
|
## V2.1.2 (2026-02-01)
|
|
|
|
### 🚀 New Features
|
|
|
|
#### Indicator Parameter Support
|
|
- **External Parameter Passing** - Indicators can now declare parameters using `# @param` syntax that can be configured per-strategy
|
|
- Supported types: `int`, `float`, `bool`, `str`
|
|
- Parameters are displayed in the strategy creation form after selecting an indicator
|
|
- Different strategies using the same indicator can have different parameter values
|
|
- **Cross-Indicator Calling** - Indicators can now call other indicators using `call_indicator(id_or_name, df)` function
|
|
- Supports calling by indicator ID (number) or name (string)
|
|
- Maximum call depth of 5 to prevent circular dependencies
|
|
- Only allows calling own indicators or published community indicators
|
|
|
|
#### Parameter Declaration Syntax
|
|
```
|
|
# @param <name> <type> <default> <description>
|
|
```
|
|
|
|
| Field | Description | Example |
|
|
|-------|-------------|---------|
|
|
| name | Parameter name (variable name) | `ma_fast` |
|
|
| type | Data type: `int`, `float`, `bool`, `str` | `int` |
|
|
| default | Default value | `5` |
|
|
| description | Description (shown in UI tooltip) | `Short-term MA period` |
|
|
|
|
#### Example: Dual Moving Average with Parameters
|
|
```python
|
|
# @param sma_short int 14 Short-term MA period
|
|
# @param sma_long int 28 Long-term MA period
|
|
|
|
# Get parameters
|
|
sma_short_period = params.get('sma_short', 14)
|
|
sma_long_period = params.get('sma_long', 28)
|
|
|
|
my_indicator_name = "Dual MA Strategy"
|
|
my_indicator_description = f"SMA{sma_short_period}/{sma_long_period} crossover"
|
|
|
|
df = df.copy()
|
|
sma_short = df["close"].rolling(sma_short_period).mean()
|
|
sma_long = df["close"].rolling(sma_long_period).mean()
|
|
|
|
# Golden cross / Death cross
|
|
buy = (sma_short > sma_long) & (sma_short.shift(1) <= sma_long.shift(1))
|
|
sell = (sma_short < sma_long) & (sma_short.shift(1) >= sma_long.shift(1))
|
|
|
|
df["buy"] = buy.fillna(False).astype(bool)
|
|
df["sell"] = sell.fillna(False).astype(bool)
|
|
|
|
# Chart markers
|
|
buy_marks = [df["low"].iloc[i] * 0.995 if df["buy"].iloc[i] else None for i in range(len(df))]
|
|
sell_marks = [df["high"].iloc[i] * 1.005 if df["sell"].iloc[i] else None for i in range(len(df))]
|
|
|
|
output = {
|
|
"name": my_indicator_name,
|
|
"plots": [
|
|
{"name": f"SMA{sma_short_period}", "data": sma_short.tolist(), "color": "#FF9800", "overlay": True},
|
|
{"name": f"SMA{sma_long_period}", "data": sma_long.tolist(), "color": "#3F51B5", "overlay": True}
|
|
],
|
|
"signals": [
|
|
{"type": "buy", "text": "B", "data": buy_marks, "color": "#00E676"},
|
|
{"type": "sell", "text": "S", "data": sell_marks, "color": "#FF5252"}
|
|
]
|
|
}
|
|
```
|
|
|
|
#### Example: Using call_indicator()
|
|
```python
|
|
# Call another indicator by name or ID
|
|
# rsi_df = call_indicator('RSI', df) # By name
|
|
# rsi_df = call_indicator(5, df) # By ID
|
|
# rsi_df = call_indicator('RSI', df, {'period': 14}) # With params
|
|
|
|
# Note: The called indicator must be created first
|
|
# and accessible (own indicator or published community indicator)
|
|
```
|
|
|
|
### 🐛 Bug Fixes
|
|
|
|
#### Dashboard Fixes
|
|
- **Fixed current positions showing records from other users** - Position synchronization now correctly associates positions with the strategy owner's user_id
|
|
- **Fixed strategy distribution pie chart always showing "No Data"** - Chart now uses `strategy_stats` data which includes all strategies with trading activity
|
|
- **Removed AI strategy count from running strategies card** - Dashboard now only shows indicator strategy count since AI strategies category has been removed
|
|
|
|
---
|
|
|
|
## V2.1.1 (2026-01-31)
|
|
|
|
### 🚀 New Features
|
|
|
|
#### AI Analysis System Overhaul
|
|
- **Fast Analysis Mode**: Replaced the complex multi-agent system with a streamlined single LLM call architecture for faster and more accurate analysis
|
|
- **Progressive Loading**: Market data now loads independently - each section (sentiment, indices, heatmap, calendar) displays as soon as it's ready
|
|
- **Professional Loading Animation**: New progress bar with step indicators during AI analysis
|
|
- **Analysis Memory**: Store analysis results for history review and user feedback
|
|
- **Stop Loss/Take Profit Calculation**: Now based on ATR (Average True Range) and Support/Resistance levels with clear methodology hints
|
|
|
|
#### Global Market Integration
|
|
- Integrated Global Market data directly into AI Analysis page
|
|
- Real-time scrolling display of major global indices with flags, prices, and percentage changes
|
|
- Interactive heatmaps for Crypto, Commodities, Sectors, and Forex
|
|
- Economic calendar with bullish/bearish/neutral impact indicators
|
|
- Commodities heatmap added (Gold, Silver, Crude Oil, etc.)
|
|
|
|
#### Indicator Community Enhancements
|
|
- **Admin Review System**: Administrators can now review, approve, reject, unpublish, and delete community indicators
|
|
- **Purchase & Rating System**: Users can buy indicators, leave ratings and comments
|
|
- **Statistics Tracking**: Purchase count, average rating, rating count, view count for each indicator
|
|
|
|
#### Trading Assistant Improvements
|
|
- Improved IBKR/MT5 connection test feedback
|
|
- Added local deployment warning for external trading platforms
|
|
- Virtual profit/loss calculation for signal-only strategies
|
|
|
|
### 🐛 Bug Fixes
|
|
- Fixed progress bar and timer not animating during AI analysis
|
|
- Fixed missing i18n translations for various components
|
|
- Fixed Tiingo API rate limit issues with caching
|
|
- Fixed data fetching with multiple fallback sources
|
|
- Fixed watchlist price batch fetch timeout handling
|
|
- Fixed heatmap multi-language support for commodities and forex
|
|
- **Fixed AI analysis history not filtered by user** - All users were seeing the same history records; now each user only sees their own analysis history
|
|
- **Fixed "Missing Turnstile token" error when changing password** - Logged-in users no longer need Turnstile verification to request password change verification code
|
|
|
|
### 🎨 UI/UX Improvements
|
|
- Reorganized left menu: Indicator Market moved below Indicator Analysis, Settings moved to bottom
|
|
- Skeleton loading animations for progressive data display
|
|
- Dark theme support for all new components
|
|
- Compact market overview bar design
|
|
|
|
### 📋 Database Migration
|
|
|
|
**Run the following SQL on your PostgreSQL database before deploying V2.1.1:**
|
|
|
|
```sql
|
|
-- ============================================================
|
|
-- QuantDinger V2.1.1 Database Migration
|
|
-- ============================================================
|
|
|
|
-- 1. AI Analysis Memory Table
|
|
CREATE TABLE IF NOT EXISTS qd_analysis_memory (
|
|
id SERIAL PRIMARY KEY,
|
|
market VARCHAR(50) NOT NULL,
|
|
symbol VARCHAR(50) NOT NULL,
|
|
decision VARCHAR(10) NOT NULL,
|
|
confidence INT DEFAULT 50,
|
|
price_at_analysis DECIMAL(24, 8),
|
|
entry_price DECIMAL(24, 8),
|
|
stop_loss DECIMAL(24, 8),
|
|
take_profit DECIMAL(24, 8),
|
|
summary TEXT,
|
|
reasons JSONB,
|
|
risks JSONB,
|
|
scores JSONB,
|
|
indicators_snapshot JSONB,
|
|
raw_result JSONB,
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
validated_at TIMESTAMP,
|
|
actual_outcome VARCHAR(20),
|
|
actual_return_pct DECIMAL(10, 4),
|
|
was_correct BOOLEAN,
|
|
user_feedback VARCHAR(20),
|
|
feedback_at TIMESTAMP
|
|
);
|
|
|
|
-- Add raw_result column if table exists but column doesn't
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'qd_analysis_memory' AND column_name = 'raw_result'
|
|
) THEN
|
|
ALTER TABLE qd_analysis_memory ADD COLUMN raw_result JSONB;
|
|
END IF;
|
|
END $$;
|
|
|
|
-- Add user_id column for user-specific history filtering
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'qd_analysis_memory' AND column_name = 'user_id'
|
|
) THEN
|
|
ALTER TABLE qd_analysis_memory ADD COLUMN user_id INT;
|
|
END IF;
|
|
END $$;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_analysis_memory_symbol ON qd_analysis_memory(market, symbol);
|
|
CREATE INDEX IF NOT EXISTS idx_analysis_memory_created ON qd_analysis_memory(created_at DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_analysis_memory_validated ON qd_analysis_memory(validated_at) WHERE validated_at IS NOT NULL;
|
|
CREATE INDEX IF NOT EXISTS idx_analysis_memory_user ON qd_analysis_memory(user_id);
|
|
|
|
-- 2. Indicator Purchase Records
|
|
CREATE TABLE IF NOT EXISTS qd_indicator_purchases (
|
|
id SERIAL PRIMARY KEY,
|
|
indicator_id INTEGER NOT NULL REFERENCES qd_indicator_codes(id) ON DELETE CASCADE,
|
|
buyer_id INTEGER NOT NULL REFERENCES qd_users(id) ON DELETE CASCADE,
|
|
seller_id INTEGER NOT NULL REFERENCES qd_users(id),
|
|
price DECIMAL(10,2) NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
UNIQUE(indicator_id, buyer_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_purchases_indicator ON qd_indicator_purchases(indicator_id);
|
|
CREATE INDEX IF NOT EXISTS idx_purchases_buyer ON qd_indicator_purchases(buyer_id);
|
|
CREATE INDEX IF NOT EXISTS idx_purchases_seller ON qd_indicator_purchases(seller_id);
|
|
|
|
-- 3. Indicator Comments
|
|
CREATE TABLE IF NOT EXISTS qd_indicator_comments (
|
|
id SERIAL PRIMARY KEY,
|
|
indicator_id INTEGER NOT NULL REFERENCES qd_indicator_codes(id) ON DELETE CASCADE,
|
|
user_id INTEGER NOT NULL REFERENCES qd_users(id) ON DELETE CASCADE,
|
|
rating INTEGER DEFAULT 5 CHECK (rating >= 1 AND rating <= 5),
|
|
content TEXT DEFAULT '',
|
|
parent_id INTEGER REFERENCES qd_indicator_comments(id) ON DELETE CASCADE,
|
|
is_deleted INTEGER DEFAULT 0,
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_comments_indicator ON qd_indicator_comments(indicator_id);
|
|
CREATE INDEX IF NOT EXISTS idx_comments_user ON qd_indicator_comments(user_id);
|
|
|
|
-- 4. Indicator Codes Extensions
|
|
DO $$
|
|
BEGIN
|
|
-- Purchase count
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'qd_indicator_codes' AND column_name = 'purchase_count'
|
|
) THEN
|
|
ALTER TABLE qd_indicator_codes ADD COLUMN purchase_count INTEGER DEFAULT 0;
|
|
END IF;
|
|
|
|
-- Average rating
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'qd_indicator_codes' AND column_name = 'avg_rating'
|
|
) THEN
|
|
ALTER TABLE qd_indicator_codes ADD COLUMN avg_rating DECIMAL(3,2) DEFAULT 0;
|
|
END IF;
|
|
|
|
-- Rating count
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'qd_indicator_codes' AND column_name = 'rating_count'
|
|
) THEN
|
|
ALTER TABLE qd_indicator_codes ADD COLUMN rating_count INTEGER DEFAULT 0;
|
|
END IF;
|
|
|
|
-- View count
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'qd_indicator_codes' AND column_name = 'view_count'
|
|
) THEN
|
|
ALTER TABLE qd_indicator_codes ADD COLUMN view_count INTEGER DEFAULT 0;
|
|
END IF;
|
|
|
|
-- Review status
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'qd_indicator_codes' AND column_name = 'review_status'
|
|
) THEN
|
|
ALTER TABLE qd_indicator_codes ADD COLUMN review_status VARCHAR(20) DEFAULT 'approved';
|
|
UPDATE qd_indicator_codes SET review_status = 'approved' WHERE publish_to_community = 1;
|
|
END IF;
|
|
|
|
-- Review note
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'qd_indicator_codes' AND column_name = 'review_note'
|
|
) THEN
|
|
ALTER TABLE qd_indicator_codes ADD COLUMN review_note TEXT DEFAULT '';
|
|
END IF;
|
|
|
|
-- Reviewed at
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'qd_indicator_codes' AND column_name = 'reviewed_at'
|
|
) THEN
|
|
ALTER TABLE qd_indicator_codes ADD COLUMN reviewed_at TIMESTAMP;
|
|
END IF;
|
|
|
|
-- Reviewed by
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'qd_indicator_codes' AND column_name = 'reviewed_by'
|
|
) THEN
|
|
ALTER TABLE qd_indicator_codes ADD COLUMN reviewed_by INTEGER;
|
|
END IF;
|
|
END $$;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_indicator_review_status ON qd_indicator_codes(review_status);
|
|
|
|
-- 5. User Table Extensions
|
|
DO $$
|
|
BEGIN
|
|
-- Token version (for single-client login)
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'qd_users' AND column_name = 'token_version'
|
|
) THEN
|
|
ALTER TABLE qd_users ADD COLUMN token_version INTEGER DEFAULT 1;
|
|
END IF;
|
|
|
|
-- Notification settings
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'qd_users' AND column_name = 'notification_settings'
|
|
) THEN
|
|
ALTER TABLE qd_users ADD COLUMN notification_settings TEXT DEFAULT '{}';
|
|
END IF;
|
|
END $$;
|
|
|
|
-- Migration Complete
|
|
DO $$
|
|
BEGIN
|
|
RAISE NOTICE '✅ QuantDinger V2.1.1 database migration completed!';
|
|
END $$;
|
|
```
|
|
|
|
### 🗑️ Removed
|
|
- Old multi-agent AI analysis system (`backend_api_python/app/services/agents/` directory)
|
|
- Old analysis routes and services
|
|
- Standalone Global Market page (merged into AI Analysis)
|
|
- Reflection worker background process
|
|
|
|
### ⚠️ Breaking Changes
|
|
- AI Analysis API endpoints changed from `/api/analysis/*` to `/api/fast-analysis/*`
|
|
- Old analysis history data is not compatible with new format
|
|
|
|
### 📝 Configuration Notes
|
|
- No new environment variables required
|
|
- Existing LLM configuration in System Settings will be used for AI Analysis
|
|
|
|
---
|
|
|
|
## Version History
|
|
|
|
| Version | Date | Highlights |
|
|
|---------|------|------------|
|
|
| V2.2.1 | 2026-02-27 | Membership & Billing, USDT TRC20 payment, VIP free indicators, AI Trading Radar, simplified strategy creation |
|
|
| V2.1.3 | 2026-02-XX | Cross-sectional strategy support |
|
|
| V2.1.2 | 2026-02-01 | Indicator parameters, cross-indicator calling |
|
|
| V2.1.1 | 2026-01-31 | AI Analysis overhaul, Global Market integration, Indicator Community enhancements |
|
|
|
|
---
|
|
|
|
*For questions or issues, please open a GitHub issue or contact the maintainers.*
|