量化策略兼容性设计
✅ 一、量化策略到底是什么?
在虚拟货币交易所中,“量化策略”可以看作是一种**“交易逻辑 + 参数配置 + 状态信息”**的组合,广义上包括以下几个部分:
1. 策略逻辑(核心代码)
- 是“如何决策买卖”的代码模块,例如:
if ma_short > ma_long and not position:buy()
- 可以是 Python、C++、JavaScript 或策略引擎的 DSL(策略描述语言)
- 有些平台会用 JSON 来配置逻辑模块(如拼积木方式)
2. 策略参数(可配置项)
比如:
{"symbol": "BTC/USDT","entry_signal": "ma_cross","ma_short": 5,"ma_long": 20,"risk_limit": 0.05
}
3. 策略状态(运行时产生的数据)
包括:
- 当前持仓
- 未完成订单列表
- 上一次触发时间
- 已触发的止盈止损标记
- 日志 / 报错信息
这些可以看作是“策略的实时快照”,在系统中周期性保存用于恢复和监控。
✅ 二、策略数据应该如何存储?
要根据不同用途选择不同存储方式,分三类:
1. 策略配置与定义(结构化 + 长期存储)
- 存储内容:策略ID、策略类型、代码路径、参数等
- 存储方式:数据库(MySQL、PostgreSQL、MongoDB)
2. 策略运行时状态(高频更新 + 快速读写)
- 存储内容:当前持仓、信号状态、PnL、运行标记
- 存储方式:Redis(内存型)或数据库中定期快照
- 用于实时监控和宕机恢复
3. 策略日志与历史数据(用于回测与审计)
- 存储内容:每一次决策、订单、成交、异常
- 存储方式:
- 日志系统(如 ELK、MongoDB)
- 时间序列数据库(InfluxDB、TimescaleDB)也可用于策略表现分析
✅ 三、一个完整的策略数据模型可以这样理解:
策略逻辑代码(Strategy Code)│├── 策略配置(参数) → 存数据库│├── 运行状态(仓位、止损标记) → Redis / DB 快照│└── 日志记录(触发、下单、成交) → MongoDB / Log
即使主策略类是用 Java 编写的,也完全可以同时支持 DSL 和脚本策略的扩展形式,关键在于如何设计整个策略执行框架的“抽象接口”与“执行器”。
下面详细解释如何做到这三种方式兼容,并给出一个建议的设计结构。
✅ 三种策略形式统一支持的目标
策略类型 | 执行方式 | 使用场景 |
---|---|---|
Java 类策略 | Spring 容器 Bean 执行 | 高性能、强依赖注入 |
DSL 策略 | 自定义语法解析 + 解释执行 | 用户可配置、低门槛策略开发 |
脚本策略 | 解释型语言如 JS/Groovy/Python | 更强灵活性、动态策略逻辑 |
✅ 核心思路:统一接口 + 多种策略执行器
1. 定义统一的策略接口
public interface Strategy {void init(Map<String, Object> params);void execute();
}
2. 不同类型的策略执行器(Executor)
public interface StrategyExecutor {void execute(StrategyDefinition def);
}
3. 数据库中策略结构推荐
{"strategyType": "JAVA", // 或 "DSL", "SCRIPT""strategyName": "gridStrategy", // Bean 名称或脚本文件名或 DSL 名称"params": {"lowerPrice": 1800,"upperPrice": 2200,"gridCount": 10}
}
✅ 不同策略类型如何执行
1. Java 策略执行器
@Component
public class JavaStrategyExecutor implements StrategyExecutor {@Autowiredprivate ApplicationContext applicationContext;public void execute(StrategyDefinition def) {Strategy strategy = (Strategy) applicationContext.getBean(def.getStrategyName());strategy.init(def.getParams());strategy.execute();}
}
2. DSL 策略执行器(伪代码示例)
public class DslStrategyExecutor implements StrategyExecutor {public void execute(StrategyDefinition def) {String dsl = loadDslScript(def.getStrategyName());DslContext ctx = DslParser.parse(dsl);ctx.bindParams(def.getParams());ctx.execute();}
}
需要定义自己的 DSL 语法(比如类似于 TradingView 的 Pine Script),或者用 Drools、MVEL 等规则引擎。
3. 脚本策略执行器(JS / Groovy)
Java 原生支持脚本语言(JS、Groovy)执行:
ScriptEngine engine = new ScriptEngineManager().getEngineByName("groovy");
engine.eval(new FileReader("scripts/myStrategy.groovy"));
✅ 设计模型
+--------------------+| StrategyScheduler |+--------------------+|+------------------------+| StrategyExecutorFactory |+------------------------+|+----------+----------+----------+| | | |JavaExec DSLExec ScriptExec ...| | |SpringBean DSL解释器 Groovy/JS
即使主策略是 Java 实现,也可以非常自然地扩展支持 DSL 或脚本策略,关键是设计一个 统一的执行接口与分发机制。
这样就能实现以下目标:
- 同一个策略调度器,可以调度 Java、DSL、脚本策略;
- 数据库中用
strategyType
做类型区分; - 对用户隐藏实现细节,统一用参数 + 策略名配置。
项目结构
这是一个简单的 Spring Boot 项目骨架,它支持 Java 策略、DSL 策略和脚本策略的执行,并且通过统一的 StrategyExecutor
来调度这些策略。
项目结构将包括:
Strategy
接口- 不同类型的
StrategyExecutor
(Java、DSL、Script) StrategyScheduler
用来管理和调度策略- 基本的数据库结构模拟
src/main/java/com/myapp/quant
├── config/
│ └── StrategyExecutorConfig.java // 配置策略执行器
├── executor/
│ ├── StrategyExecutor.java // 执行器接口
│ ├── JavaStrategyExecutor.java // Java 执行器
│ ├── DslStrategyExecutor.java // DSL 执行器
│ └── ScriptStrategyExecutor.java // 脚本执行器
├── strategy/
│ ├── Strategy.java // 策略接口
│ └── GridStrategy.java // Java 策略实现
├── scheduler/
│ └── StrategyScheduler.java // 策略调度器
└── model/└── StrategyDefinition.java // 策略数据结构
核心代码实现
Strategy.java
— 策略接口
package com.myapp.quant.strategy;import java.util.Map;public interface Strategy {void init(Map<String, Object> params); // 初始化策略参数void execute(); // 执行策略
}
GridStrategy.java
— Java 策略实现
package com.myapp.quant.strategy;import org.springframework.stereotype.Component;import java.util.Map;@Component("gridStrategy")
public class GridStrategy implements Strategy {private int lowerPrice;private int upperPrice;private int gridCount;@Overridepublic void init(Map<String, Object> params) {this.lowerPrice = (int) params.get("lowerPrice");this.upperPrice = (int) params.get("upperPrice");this.gridCount = (int) params.get("gridCount");}@Overridepublic void execute() {System.out.println("Running Grid Strategy: Lower Price " + lowerPrice + ", Upper Price " + upperPrice + ", Grid Count " + gridCount);}
}
StrategyExecutor.java
— 策略执行器接口
package com.myapp.quant.executor;import com.myapp.quant.model.StrategyDefinition;public interface StrategyExecutor {void execute(StrategyDefinition def);
}
JavaStrategyExecutor.java
— Java 执行器实现
package com.myapp.quant.executor;import com.myapp.quant.model.StrategyDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;@Component
public class JavaStrategyExecutor implements StrategyExecutor {@Autowiredprivate ApplicationContext applicationContext;@Overridepublic void execute(StrategyDefinition def) {// 获取 Spring 管理的 BeanStrategy strategy = (Strategy) applicationContext.getBean(def.getStrategyName());strategy.init(def.getParams());strategy.execute();}
}
DslStrategyExecutor.java
— DSL 执行器实现(伪代码)
package com.myapp.quant.executor;import com.myapp.quant.model.StrategyDefinition;
import org.springframework.stereotype.Component;@Component
public class DslStrategyExecutor implements StrategyExecutor {@Overridepublic void execute(StrategyDefinition def) {String dslScript = loadDslScript(def.getStrategyName());DslContext context = parseDsl(dslScript);context.bindParams(def.getParams());context.execute();}private String loadDslScript(String strategyName) {// 模拟加载 DSL 脚本return "DSL script for " + strategyName;}private DslContext parseDsl(String dslScript) {// 模拟解析 DSLreturn new DslContext();}
}
ScriptStrategyExecutor.java
— 脚本执行器实现(以 Groovy 为例)
package com.myapp.quant.executor;import com.myapp.quant.model.StrategyDefinition;
import org.springframework.stereotype.Component;import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;@Component
public class ScriptStrategyExecutor implements StrategyExecutor {@Overridepublic void execute(StrategyDefinition def) {String script = loadScript(def.getStrategyName());executeScript(script);}private String loadScript(String strategyName) {// 模拟加载脚本return "println('Running " + strategyName + " script')";}private void executeScript(String script) {ScriptEngine engine = new ScriptEngineManager().getEngineByName("groovy");try {engine.eval(script);} catch (Exception e) {e.printStackTrace();}}
}
Python 执行器
创建一个新的 PythonStrategyExecutor
来执行 Python 脚本。可以通过 Jython(Python 的 Java 实现)或者通过 ProcessBuilder 直接调用 Python 解释器来执行 Python 脚本。选择 ProcessBuilder
调用本地的 Python 解释器来执行 Python 脚本。这样做的好处是更加通用,并且不依赖 Java 和 Python 之间的直接集成,可以自由执行任何 Python 脚本。
package com.myapp.quant.executor;import com.myapp.quant.model.StrategyDefinition;
import org.springframework.stereotype.Component;import java.io.BufferedReader;
import java.io.InputStreamReader;@Component
public class PythonStrategyExecutor implements StrategyExecutor {@Overridepublic void execute(StrategyDefinition def) {String script = loadPythonScript(def.getStrategyName());executePythonScript(script);}private String loadPythonScript(String strategyName) {// 模拟加载 Python 脚本(可以从文件或数据库中加载)return "print('Running Python strategy: " + strategyName + "')";}private void executePythonScript(String script) {try {// 写入 Python 脚本到文件ProcessBuilder processBuilder = new ProcessBuilder("python", "-c", script);processBuilder.redirectErrorStream(true);Process process = processBuilder.start();// 获取 Python 脚本输出BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));String line;while ((line = reader.readLine()) != null) {System.out.println(line);}process.waitFor(); // 等待脚本执行完毕} catch (Exception e) {e.printStackTrace();}}
}
StrategyScheduler.java
— 策略调度器
package com.myapp.quant.scheduler;import com.myapp.quant.executor.StrategyExecutor;
import com.myapp.quant.model.StrategyDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class StrategyScheduler {@Autowiredprivate StrategyExecutor javaStrategyExecutor;@Autowiredprivate StrategyExecutor dslStrategyExecutor;@Autowiredprivate StrategyExecutor scriptStrategyExecutor;@Autowiredprivate StrategyExecutor pythonStrategyExecutor;public void scheduleStrategy(StrategyDefinition strategyDef) {// 根据策略类型选择对应的执行器switch (strategyDef.getStrategyType()) {case "JAVA":javaStrategyExecutor.execute(strategyDef);break;case "DSL":dslStrategyExecutor.execute(strategyDef);break;case "SCRIPT":scriptStrategyExecutor.execute(strategyDef);break;case "PYTHON":pythonStrategyExecutor.execute(strategyDef);break;default:throw new IllegalArgumentException("Unknown strategy type");}}
}
StrategyDefinition.java
— 策略定义数据结构
package com.myapp.quant.model;import java.util.Map;public class StrategyDefinition {private String strategyName; // 策略名称(对应 Spring Bean 或脚本名)private String strategyType; // 策略类型 (JAVA / DSL / SCRIPT)private Map<String, Object> params; // 策略参数// Getters and Setters
}
数据库策略数据结构示例
在数据库中,策略数据可以类似这样存储:
id | strategyName | strategyType | params |
---|---|---|---|
1 | gridStrategy | JAVA | {“lowerPrice”: 1800, “upperPrice”: 2200, “gridCount”: 10} |
2 | martingaleScript | SCRIPT | {“initialAmount”: 100, “multiplier”: 2} |
3 | customDsl | DSL | {“param1”: “value1”, “param2”: “value2”} |
4 | pythonStrategy | PYTHON | {“param1”: “value1”, “param2”: “value2”} |
总结
JavaStrategyExecutor
:执行 Spring 管理的 Java 策略。DslStrategyExecutor
:执行自定义 DSL 策略(你可以通过 DSL 解析器来扩展)。ScriptStrategyExecutor
:执行脚本语言策略(如 Groovy、JavaScript)。StrategyScheduler
:调度器负责选择并执行正确的策略执行器。