DEOptim变量约束:强制一个变量小于另一个
在DEOptim中实现变量间的大小约束(以移动均线策略为例)
我之前优化双均线策略时也遇到过一模一样的问题——必须保证短周期均线的参数小于长周期的,折腾了几种方法后,总结出两个最实用的方案,分享给你:
方法1:变量替换(最稳妥的方案)
核心思路是从变量定义上直接保证约束成立,避免后续处理的麻烦。比如我们需要优化的两个参数是短周期n_short和长周期n_long,要求n_short < n_long,那我们可以把变量重新定义为:
n_short:直接作为优化变量,范围设为你需要的最小值到最大值(比如5到30)delta:表示两个周期的最小间隔,设为优化变量,范围从1到你能接受的最大间隔(比如1到30)- 最终的长周期参数就是
n_long = n_short + delta
这样不管DEOptim怎么优化,n_long天然大于n_short,完全不需要额外判断。下面是代码示例:
library(DEoptim) library(TTR) # 用于计算移动均线 # 定义目标函数(双均线策略的收益计算,这里用模拟数据举例) ma_strategy_profit <- function(x) { n_short <- x[1] delta <- x[2] n_long <- n_short + delta # 替换成你实际的行情数据和策略逻辑 set.seed(123) # 固定种子方便复现 price <- cumsum(rnorm(1000)) + 100 ma_short <- SMA(price, n_short) ma_long <- SMA(price, n_long) signal <- ifelse(ma_short > ma_long, 1, -1) returns <- diff(price)/price[-length(price)] strategy_returns <- signal[-length(signal)] * returns total_profit <- sum(strategy_returns) # DEOptim默认是最小化,所以如果要最大化收益,返回负的收益 return(-total_profit) } # 设置优化参数范围 lower <- c(5, 1) # n_short最小5,delta最小1 upper <- c(30, 30) # n_short最大30,delta最大30 # 运行DEOptim result <- DEoptim(ma_strategy_profit, lower = lower, upper = upper) # 提取最优参数 best_n_short <- result$optim$bestmem[1] best_n_long <- best_n_short + result$optim$bestmem[2] cat("最优短周期:", best_n_short, "\n最优长周期:", best_n_long, "\n")
方法2:惩罚函数法(灵活但需调试)
如果不想改变量定义,可以在目标函数里加入惩罚项:当约束不满足时,给目标函数一个极端值,让DEOptim自动避开这类解。
比如我们还是直接优化n_short和n_long,当n_short >= n_long时,返回一个非常小的收益(如果是最大化收益的话,就返回负的极大值;如果是最小化风险,就返回正的极大值)。代码示例:
library(DEoptim) library(TTR) ma_strategy_profit_with_penalty <- function(x) { n_short <- x[1] n_long <- x[2] # 约束检查:如果短周期 >= 长周期,返回极端惩罚值 if(n_short >= n_long) { return(-1e9) # 因为DEOptim默认最小化,我们要最大化收益,所以返回负的极大值 } # 正常的策略收益计算 set.seed(123) price <- cumsum(rnorm(1000)) + 100 ma_short <- SMA(price, n_short) ma_long <- SMA(price, n_long) signal <- ifelse(ma_short > ma_long, 1, -1) returns <- diff(price)/price[-length(price)] strategy_returns <- signal[-length(signal)] * returns total_profit <- sum(strategy_returns) return(-total_profit) } # 设置参数范围(这里n_short和n_long可以有重叠,但惩罚会过滤掉不符合的) lower <- c(5, 5) upper <- c(60, 60) result <- DEoptim(ma_strategy_profit_with_penalty, lower = lower, upper = upper) best_n_short <- result$optim$bestmem[1] best_n_long <- result$optim$bestmem[2] cat("最优短周期:", best_n_short, "\n最优长周期:", best_n_long, "\n")
两种方法的对比
- 变量替换法:完全避免违反约束的情况,优化效率更高,推荐优先使用,尤其是这种固定顺序的约束。
- 惩罚函数法:不需要修改变量结构,适合复杂约束,但需要调整惩罚值——惩罚太小可能会出现违反约束的解,惩罚太大可能让优化陷入局部最优。
内容的提问来源于stack exchange,提问作者thatmathsgeezer
相关产品推荐
相关产品推荐

