增加小时限制

This commit is contained in:
薇薇安 2026-03-05 08:43:03 +08:00
parent 6858ddad6b
commit 218ab7e195
6 changed files with 42 additions and 0 deletions

View File

@ -46,6 +46,7 @@ USER_RISK_KNOBS = {
"NIGHT_HOURS_START", "NIGHT_HOURS_START",
"NIGHT_HOURS_END", "NIGHT_HOURS_END",
"NIGHT_HOURS_ONLY_SUNDAY", "NIGHT_HOURS_ONLY_SUNDAY",
"NO_OPEN_HOURS_BJ",
# 策略筛选(允许用户调整) # 策略筛选(允许用户调整)
"TOP_N_SYMBOLS", "TOP_N_SYMBOLS",
"MIN_SIGNAL_STRENGTH", "MIN_SIGNAL_STRENGTH",
@ -73,6 +74,7 @@ USER_VISIBLE_DEFAULTS = {
"NIGHT_HOURS_START": {"value": 21, "type": "number", "category": "risk", "description": "禁止开仓开始小时(含)"}, "NIGHT_HOURS_START": {"value": 21, "type": "number", "category": "risk", "description": "禁止开仓开始小时(含)"},
"NIGHT_HOURS_END": {"value": 6, "type": "number", "category": "risk", "description": "禁止开仓结束小时(不含)"}, "NIGHT_HOURS_END": {"value": 6, "type": "number", "category": "risk", "description": "禁止开仓结束小时(不含)"},
"NIGHT_HOURS_ONLY_SUNDAY": {"value": True, "type": "boolean", "category": "risk", "description": "True=仅周六21:00周日06:00False=每天"}, "NIGHT_HOURS_ONLY_SUNDAY": {"value": True, "type": "boolean", "category": "risk", "description": "True=仅周六21:00周日06:00False=每天"},
"NO_OPEN_HOURS_BJ": {"value": "", "type": "string", "category": "risk", "description": "禁止开仓小时(北京)逗号分隔如17,19,22空则不限制"},
"TOP_N_SYMBOLS": {"value": 8, "type": "number", "category": "scan", "description": "每次扫描后优先处理的交易对数量"}, "TOP_N_SYMBOLS": {"value": 8, "type": "number", "category": "scan", "description": "每次扫描后优先处理的交易对数量"},
"MIN_SIGNAL_STRENGTH": {"value": 8, "type": "number", "category": "scan", "description": "最小信号强度0-10"}, "MIN_SIGNAL_STRENGTH": {"value": 8, "type": "number", "category": "scan", "description": "最小信号强度0-10"},
"MIN_VOLUME_24H": {"value": 30_000_000, "type": "number", "category": "scan", "description": "24h 成交量下限USD"}, "MIN_VOLUME_24H": {"value": 30_000_000, "type": "number", "category": "scan", "description": "24h 成交量下限USD"},
@ -123,6 +125,7 @@ RISK_KNOBS_DEFAULTS = {
"NIGHT_HOURS_START": {"value": 21, "type": "number", "category": "risk", "description": "禁止开仓开始小时(北京),含"}, "NIGHT_HOURS_START": {"value": 21, "type": "number", "category": "risk", "description": "禁止开仓开始小时(北京),含"},
"NIGHT_HOURS_END": {"value": 6, "type": "number", "category": "risk", "description": "禁止开仓结束小时(北京),不含"}, "NIGHT_HOURS_END": {"value": 6, "type": "number", "category": "risk", "description": "禁止开仓结束小时(北京),不含"},
"NIGHT_HOURS_ONLY_SUNDAY": {"value": True, "type": "boolean", "category": "risk", "description": "仅周日夜间。True=周六21:00周日06:00False=每天。"}, "NIGHT_HOURS_ONLY_SUNDAY": {"value": True, "type": "boolean", "category": "risk", "description": "仅周日夜间。True=周六21:00周日06:00False=每天。"},
"NO_OPEN_HOURS_BJ": {"value": "", "type": "string", "category": "risk", "description": "禁止开仓小时(北京),逗号分隔如 17,19,22 表示 17/19/22 时不开新仓;空则不限制。按历史亏损时段配置。"},
} }
# API key/secret 脱敏 # API key/secret 脱敏

View File

@ -836,6 +836,7 @@ class ConfigManager:
'NIGHT_HOURS_START': eff_get('NIGHT_HOURS_START', 21), 'NIGHT_HOURS_START': eff_get('NIGHT_HOURS_START', 21),
'NIGHT_HOURS_END': eff_get('NIGHT_HOURS_END', 6), 'NIGHT_HOURS_END': eff_get('NIGHT_HOURS_END', 6),
'NIGHT_HOURS_ONLY_SUNDAY': eff_get('NIGHT_HOURS_ONLY_SUNDAY', True), 'NIGHT_HOURS_ONLY_SUNDAY': eff_get('NIGHT_HOURS_ONLY_SUNDAY', True),
'NO_OPEN_HOURS_BJ': (eff_get('NO_OPEN_HOURS_BJ', '') or '').strip(), # 禁止开仓小时(北京),逗号分隔如 "17,19,22",空则不限制
# 同步/系统单标识(全局配置,账号可覆盖) # 同步/系统单标识(全局配置,账号可覆盖)
'ONLY_AUTO_TRADE_CREATES_RECORDS': eff_get('ONLY_AUTO_TRADE_CREATES_RECORDS', True), # True=不补建「仅币安有仓」False 时配合 SYNC_RECOVER 可补建 'ONLY_AUTO_TRADE_CREATES_RECORDS': eff_get('ONLY_AUTO_TRADE_CREATES_RECORDS', True), # True=不补建「仅币安有仓」False 时配合 SYNC_RECOVER 可补建

View File

@ -68,6 +68,18 @@
--- ---
### 6. 禁止开仓小时(按历史亏损时段)
若导出数据里**按小时**统计后,某些整点(如 17、19、22 时北京)亏损集中,可单独禁止这些整点开新仓:
| 配置项 | 建议值 | 说明 |
|--------|--------|------|
| **NO_OPEN_HOURS_BJ** | **17,19,22** | 北京 17/19/22 时不开新仓;逗号分隔,空则不限制。 |
配置后,交易进程在对应整点会跳过开仓并打日志「当前北京 X 时在禁止开仓时段内」。
---
## 三、操作清单(复制自查) ## 三、操作清单(复制自查)
- [ ] **BLOCK_SHORT_WHEN_4H_UP** = true - [ ] **BLOCK_SHORT_WHEN_4H_UP** = true
@ -76,6 +88,7 @@
- [ ] **MIN_SIGNAL_STRENGTH** = 68 - [ ] **MIN_SIGNAL_STRENGTH** = 68
- [ ] (可选)**SUNDAY_MAX_OPENS** = 23**SUNDAY_MIN_SIGNAL_STRENGTH** = 8 - [ ] (可选)**SUNDAY_MAX_OPENS** = 23**SUNDAY_MIN_SIGNAL_STRENGTH** = 8
- [ ] (可选)**NIGHT_HOURS_NO_OPEN_ENABLED** = true - [ ] (可选)**NIGHT_HOURS_NO_OPEN_ENABLED** = true
- [ ] (可选)**NO_OPEN_HOURS_BJ** = **17,19,22**(按你的亏损时段改)
改完后在配置页点**保存**;配置会写入数据库/Redis交易进程下一次读配置即生效一般**无需重启**(若你部署方式有缓存,可按需重启一次交易服务)。 改完后在配置页点**保存**;配置会写入数据库/Redis交易进程下一次读配置即生效一般**无需重启**(若你部署方式有缓存,可按需重启一次交易服务)。

View File

@ -46,6 +46,7 @@ const KEY_LABELS = {
NIGHT_HOURS_START: '禁止开仓开始(时)', NIGHT_HOURS_START: '禁止开仓开始(时)',
NIGHT_HOURS_END: '禁止开仓结束(时)', NIGHT_HOURS_END: '禁止开仓结束(时)',
NIGHT_HOURS_ONLY_SUNDAY: '仅周六21点周日06点', NIGHT_HOURS_ONLY_SUNDAY: '仅周六21点周日06点',
NO_OPEN_HOURS_BJ: '禁止开仓小时(北京)',
SCAN_STAGGER_BY_ACCOUNT: '多账号错峰扫描', SCAN_STAGGER_BY_ACCOUNT: '多账号错峰扫描',
SCAN_STAGGER_RANDOM: '错峰随机模式', SCAN_STAGGER_RANDOM: '错峰随机模式',
SCAN_STAGGER_MIN_SEC: '错峰最小延迟(秒)', SCAN_STAGGER_MIN_SEC: '错峰最小延迟(秒)',
@ -109,6 +110,7 @@ const CONFIG_GUIDE_DETAILS = {
NIGHT_HOURS_START: '禁止开仓开始小时(北京),含', NIGHT_HOURS_START: '禁止开仓开始小时(北京),含',
NIGHT_HOURS_END: '禁止开仓结束小时(北京),不含', NIGHT_HOURS_END: '禁止开仓结束小时(北京),不含',
NIGHT_HOURS_ONLY_SUNDAY: 'True=仅周六21:00周日06:00禁止False=每天21:0006:00禁止', NIGHT_HOURS_ONLY_SUNDAY: 'True=仅周六21:00周日06:00禁止False=每天21:0006:00禁止',
NO_OPEN_HOURS_BJ: '禁止开仓小时(北京),逗号分隔如 17,19,22 表示该整点不开新仓;空则不限制。按历史亏损时段配置。',
BINANCE_API_KEY: '币安API密钥。用于访问币安账户的凭证需要启用"合约交易"权限。请妥善保管,不要泄露。', BINANCE_API_KEY: '币安API密钥。用于访问币安账户的凭证需要启用"合约交易"权限。请妥善保管,不要泄露。',
BINANCE_API_SECRET: '币安API密钥Secret。与API Key配对使用用于签名验证。请妥善保管不要泄露。', BINANCE_API_SECRET: '币安API密钥Secret。与API Key配对使用用于签名验证。请妥善保管不要泄露。',
USE_TESTNET: '是否使用币安测试网。true表示模拟交易无真实资金false表示真实交易。', USE_TESTNET: '是否使用币安测试网。true表示模拟交易无真实资金false表示真实交易。',
@ -627,6 +629,7 @@ const GlobalConfig = () => {
NIGHT_HOURS_START: { value: 21, type: 'number', category: 'risk', description: '禁止开仓开始小时(北京),含。从周六晚 21 点开始控制。' }, NIGHT_HOURS_START: { value: 21, type: 'number', category: 'risk', description: '禁止开仓开始小时(北京),含。从周六晚 21 点开始控制。' },
NIGHT_HOURS_END: { value: 6, type: 'number', category: 'risk', description: '禁止开仓结束小时(北京),不含。' }, NIGHT_HOURS_END: { value: 6, type: 'number', category: 'risk', description: '禁止开仓结束小时(北京),不含。' },
NIGHT_HOURS_ONLY_SUNDAY: { value: true, type: 'boolean', category: 'risk', description: 'True=仅周六21:00周日06:00禁止False=每天21:0006:00禁止。' }, NIGHT_HOURS_ONLY_SUNDAY: { value: true, type: 'boolean', category: 'risk', description: 'True=仅周六21:00周日06:00禁止False=每天21:0006:00禁止。' },
NO_OPEN_HOURS_BJ: { value: '', type: 'string', category: 'risk', description: '禁止开仓小时(北京),逗号分隔如 17,19,22 表示该整点不开新仓;空则不限制。按历史亏损时段配置。' },
} }
const loadConfigs = async () => { const loadConfigs = async () => {

View File

@ -194,6 +194,8 @@ DEFAULT_TRADING_CONFIG = {
'NIGHT_HOURS_START': 21, 'NIGHT_HOURS_START': 21,
'NIGHT_HOURS_END': 6, 'NIGHT_HOURS_END': 6,
'NIGHT_HOURS_ONLY_SUNDAY': True, 'NIGHT_HOURS_ONLY_SUNDAY': True,
# 禁止开仓小时(北京):逗号分隔,如 "17,19,22" 表示 17/19/22 时不开新仓;空则不限制。按历史亏损时段配置
'NO_OPEN_HOURS_BJ': '',
'ONE_WAY_POSITION_ONLY': True, # 账号固定为单向持仓模式,不传 positionSide不检测对冲模式避免 -4061 'ONE_WAY_POSITION_ONLY': True, # 账号固定为单向持仓模式,不传 positionSide不检测对冲模式避免 -4061
'MAX_POSITION_PERCENT': 0.20, # 单笔仓位上限20%(作为风控熔断,实际仓位由固定风险模型决定) 'MAX_POSITION_PERCENT': 0.20, # 单笔仓位上限20%(作为风控熔断,实际仓位由固定风险模型决定)

View File

@ -923,6 +923,26 @@ class RiskManager:
except Exception: except Exception:
pass pass
# 禁止开仓小时(北京):按历史亏损时段配置,如 "17,19,22" 表示 17/19/22 时不开新仓
try:
no_open_hours_raw = config.TRADING_CONFIG.get("NO_OPEN_HOURS_BJ") or ""
if no_open_hours_raw and isinstance(no_open_hours_raw, str):
bj = timezone(timedelta(hours=8))
now_bj = datetime.now(bj)
h = now_bj.hour
parts = [x.strip() for x in no_open_hours_raw.split(",") if x.strip()]
no_open_set = set()
for p in parts:
try:
no_open_set.add(int(p))
except ValueError:
continue
if no_open_set and h in no_open_set:
logger.info(f"{symbol} 当前北京{h}时在禁止开仓时段内NO_OPEN_HOURS_BJ={no_open_hours_raw}),跳过")
return False
except Exception:
pass
# 每日开仓次数限制Redis 计数;无 Redis 时降级为内存计数) # 每日开仓次数限制Redis 计数;无 Redis 时降级为内存计数)
try: try:
max_daily = int(config.TRADING_CONFIG.get("MAX_DAILY_ENTRIES", 0) or 0) max_daily = int(config.TRADING_CONFIG.get("MAX_DAILY_ENTRIES", 0) or 0)