本文仅为学习笔记,无法保证正确性,不可作为交易参考。
在市场上有一个被奉为真理的加仓方法——倒金字塔加仓,传说只要按照倒金字塔加仓,一定不会亏损;今天就对这一方法利用宽客平台实现一下。
1、算法逻辑
1、分别选取次新板块和沪深300;
2、过滤上市不满30天股票;
3、为了不让平台珍贵的运算能力浪费在我这无聊的代码运行过程,随机选取50支;
4、初始建仓10%;
5、每当个股持仓亏损达到10%时,加仓一倍;
6、个股浮盈20%,止盈操作;
7、仓位达到90%时,开始对亏损超过15%的股票进行止损;
8、建仓后只平仓或加仓,不再开仓
2、代码实现(以次新板块为例)
# 导入函数库
from jqdata import *
import numpy as np
from datetime import timedelta
# 初始化函数,设定基准等等
def initialize(context):
g.stock_size = 50
g.init_flag = False
# 设定沪深300作为基准
set_benchmark('000300.XSHG')
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 输出内容到日志 log.info()
log.info('初始函数开始运行且全局只运行一次')
# 过滤掉order系列API产生的比error级别低的log
# log.set_level('order', 'error')
g.stocks = get_concept_stocks('GN189')
### 股票相关设定 ###
# 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
## 运行函数(reference_security为运行时间的参考标的;传入的标的只做种类区分,因此传入'000300.XSHG'或'510300.XSHG'是一样的)
# 开盘时运行
run_daily(market_open, time='open', reference_security='000300.XSHG')
# 收盘后运行
run_daily(after_market_close, time='after_close', reference_security='000300.XSHG')
## 开盘时运行函数
def market_open(context):
init_percent = 0.1
log.info('函数运行时间(market_open):'+str(context.current_dt.time()))
security_list = np.array(g.stocks)
security_list = [s for s in np.random.choice(security_list, size=100) if (not get_current_data()[s].paused) and ((context.current_dt.date() - get_security_info(s).start_date) > timedelta(30))]
security_list = np.array(security_list)
cash = context.portfolio.positions_value
all_cash = context.portfolio.total_value
g.pos = cash / all_cash
g.target_value = all_cash * init_percent
g.per_socket_value = g.target_value / g.stock_size
log.info('positions: {}'.format(g.pos))
if g.init_flag:
positions = [s for s in context.portfolio.positions.keys() if not get_current_data()[s].paused]
for s in positions:
avg = context.portfolio.positions[s].avg_cost
p = context.portfolio.positions[s].price
pct = (p - avg) / avg
log.info('s:{}, pct:{}'.format(s, pct))
if pct > 0.2:
order_target(s, 0, MarketOrderStyle())
if g.pos < 0.9:
if pct < -0.10:
order(s, context.portfolio.positions[s].total_amount, MarketOrderStyle())
else:
if pct < -0.15:
order_target(s, 0, MarketOrderStyle())
else:
init_order(context, security_list)
# log.info('pos:{}'.format(context.portfolio.positions_value / context.portfolio.total_value))
def init_order(context, security_list):
for s in np.random.choice(security_list, size=g.stock_size):
order_value(s, g.per_socket_value, MarketOrderStyle())
# 收盘后运行函数
def after_market_close(context):
g.init_flag = True
orders = get_open_orders()
for o in orders.values():
cancel_order(o)
3、回测(其中一次回测效果)
4、总结
1、initialize全局只运行一次;
2、初始化全局变量g时,要考虑运行频率;