最近做了一个A股自动套利交易的系统,说下我的大致思路,欢迎交流。
A股T+1的特性,没法像T0高频量化那样通过极快的速度和精确的算法在市场中获取微利,并通过高频率交易累积收益。它对技术、基础设施、算法模型的要求极高。
我就想着做一个适合自己的做T套利系统。跟价值投资客,超短龙头选手不同,希望通过小步快跑的方式累计收益,不求快,能让收益曲线趋于平稳上升就行,控制回撤也是第一要义。
一、标的选择
套利标的需要人工选择,这个没办法交给程序来筛选
- 成交额要够大,一般全市场成交额前50内
- 只参与上升趋势中的标的,下降通道的回避,一般以MA20为趋势分界线,长期保持在MA5以上的主升浪标的最佳
- 每段时间都有一两个板块热炒,分散参与其中的大容量核心标的是不错的选择
- 单边下跌,主跌段的票是必须要回避的,主跌段的标的是一切策略的梦魇
二、止损及禁止买入原则
控制回撤是最重要的事情。
- 不管什么策略,什么标的,都必须有强制止损线,可以是绝对值,也可以是当前策略买入上限金额的百分比。我一般设置的-7%
- 回避主跌段(待开发):当标的放量跌破重要趋势线,增大做T的振幅或者暂停买入、甚至直接清仓
三、套利及止盈策略
当前设置了2个策略level
- level_1比level_2的单笔买入金额,买入总金额都更大一些,适用于当前市场最热门的标的,核心中军。股性最活跃,振幅设置的±1.5%
- level_2单笔金额更小,总金额也更小,振幅设置的±2.5%,适用于当前市场第二梯队主升浪的标的
- 都设置了底仓不卖出开关、炸板清仓开关
- 向上过分偏离MA5时可以清仓(待开发)
- 盈利超过一定比例或者绝对值,可以清仓
总结为一句话就是,每次买入或卖出后就根据波动率更新下一次买入和卖出的时间,当实时价格触及到这2个价格的时候就自动买入或卖出:
java
/**
* 更新下一个低吸,卖出价格
* <p>
* 亏损状态下,按最低买入价格计算下一个买入卖出时间是可以的,但是盈利状态下的买卖不能这么计算
* <p>
* 若实现了盈利,收盘后把所有未清仓的买入记录的买入价格阶梯式更新,间隔就是波动率,这样第二天再重新计算买入卖出价格时就是以今日收盘价为基准
*/
public void updateSuckSalePrice(Momentum momentum, StockRealTimePrice stockRealTimePrice) {
List<TradingRecord> tradingRecords = tradingRecordDao.selectList(new LambdaQueryWrapper<TradingRecord>().eq(TradingRecord::getClearance, false).eq(TradingRecord::getCode, momentum.getCode()));
if (CollectionUtils.isEmpty(tradingRecords)) {
return;
}
TradingRecord tradingRecord = tradingRecords.stream().min(Comparator.comparing(TradingRecord::getBuyPrice)).get();
//从所有未卖出的买单中选择最低买入价那个作为计算标准
//更新目前的最低买入价格
momentum.setMinBuyPrice(tradingRecord.getBuyPrice().setScale(2, RoundingMode.HALF_UP));
//更新下一个卖出价格为目前所有持仓最低买入价格*做T波动差
momentum.setNextSalePrice(tradingRecord.getBuyPrice().multiply(momentum.getMS().getTRate()).setScale(2, RoundingMode.HALF_UP));
//更新下一个低吸价格为当前卖出价*低吸波动差
momentum.setNextSuckPrice(BigDecimal.valueOf(stockRealTimePrice.getCurrentPrice()).multiply(momentum.getMS().getSuckRate()).setScale(2, RoundingMode.HALF_UP));
insertLog(stockRealTimePrice, "更新下一次卖出价格为" + momentum.getNextSalePrice() + ",更新下一次低吸价格为" + momentum.getNextSuckPrice());
List<StockVo> stockHoldings = getStockHoldings();
Map<String, StockVo> map = stockHoldings.stream().collect(Collectors.toMap(StockVo::getName, e -> e));
StockVo stockVo = map.get(momentum.getName());
momentum.setHoldNumber(stockVo.getTotalVolume());
momentum.setAvailableNumber(stockVo.getAvailableVolume());
momentum.setProfit(stockVo.getProfit());
momentum.setCostPrice(stockVo.getCostPrice());
momentumDao.updateById(momentum);
}
四、自动建仓
- 未建仓的核心标的,开启波动监控,向下偏离MA5,或是盘中突然的深水,自动建仓(待开发)
五、性能与速度
虽然是低频套利交易,但是对并发及性能的要求也是必不可少的。
硬件层面:最好一个逻辑处理单元只监控一个标的。服务器逻辑处理单元数量 > 监控标的数量那就是最好的了。
软件层面:追求最佳的并发速度
关于并发在交易中的运用我会另写一篇文章,介绍一下我给朋友开发的打板系统。从发现交易所的上一档成交数据->验证策略->下单成功返回。基本在0.85秒-1秒中间完成。大大提高了打板速度与打进成功率。实测了一段时间比打板器要更快一些。