小白量化《穿云箭集群量化》(8) 核聚变策略
上一篇介绍了超级订单SuperOrder功能在股票上买入策略,这篇介绍MetaTrader5期货外汇的双向交易策略。
交易策略比较有名的是马丁策略,马丁策略是单向策略。
我们设计了双向策略原子弹策略,原子弹策略原理类似马丁策略,不同是我们采用了反向加仓规则。这样确保正确的方向,订单量最大。
无论马丁策略和原子弹策略,他们理论上,只要本金足够,肯定会盈利。因此需要很多资金才能操作。
我们在原子弹策略基础上进行改进,增加了反向回撤止盈机制,因此在方向转变时,首先止盈反向盈利订单,再按订单差开单。这样处理,会减少总订单数量,因此使用较少资金,就可以完成一次交易。
下面我们给出穿云箭量化平台的高级_MetaTrader5核聚变策略全部源代码,修改账户密码后可以直接在穿云箭量化平台中运行,
策略名='高级_MetaTrader5核聚变策略'
'''
声明:本策略不保证能赚钱,使用要求如下。
1、本策略是为客户设计演示策略,供用户学习使用。
2、首先选择一个活跃的货币对品种。
3、设置好看多看空的参数,以及回撤止盈参数。
4、系统会自动化交易。
5、切记:控制好仓位杠杆比例。
缺陷:在单边上涨时,有反向单,会产生较大回撤。
'''
修改日期='2023-05-19'
导入 pandas 命名为 pd
导入 HP_global 命名为 hg #建立全局数据域hg
从 HP_formula 导入 * #小白量化公式库
导入 HP_formula 命名为 gs #小白量化公式库
从 HP_factor 导入 * #小白量化多因子公式库
导入 HP_factor 命名为 hf #小白量化多因子公式库
导入 HP_quant 命名为 hpq #穿云箭量化框架库
从 HP_quant 导入 * #穿云箭量化框架库
导入 time
导入 MetaTrader5 命名为 mt5 #MetaTrader5自带模块
导入 HP_mt5a 命名为 hmt5 #穿云箭量化MetaTrader5增强库
server='ICMarketsSC-Demo' #服务器名
login= #用户名
password=' ' #密码
filename='%d.mem'%login
filename2='%d.mem'%login
#初始化小白mt5库
hmt5.init()
hmt5.login(login=login,server=server,password=password)
#输出mt5软件信息及连接相关信息
mt5info=hmt5.terminal_info()
mt5软件名称=mt5info.name
mt5软件语言=mt5info.language
mt5软件所属公司=mt5info.company
mt5软件路径=mt5info.path
输出()
输出('----------软件信息----------')
输出('mt5软件名称:',mt5软件名称)
输出('mt5软件语言:',mt5软件语言)
输出('mt5软件所属公司:',mt5软件所属公司)
输出('mt5软件路径:',mt5软件路径)
cruise_missile=hf.SuperOrder()
函数 初始化(context):
#context.istest=True
context.zh='xiaobai' #账户
context.zhlx='回测' #账户类型,2个汉字
context.firstcash=10000.00 #初始现金
context.cash=context.firstcash
context.portfolio.available_cash=context.firstcash
set_maxdays(300)
# 设置我们要操作的股票池
g.stocks=hpq.get_universe()
hpq.log.info('----策略环境信息-----')
hpq.log.info('量化模块版本: '+str(hpq.ver))
hpq.log.info('量化模块最后修改日期: '+str(hpq.mdate))
hpq.log.info('svrip: '+hpq.svrip)
hpq.log.info('svrport: '+str(hpq.svrport))
hpq.log.info('\n----开始运行策略-----\n')
hpq.log.info('策略名:'+策略名)
qhcsj2=time.strftime('%Y%m%d %H:%M:%S')
hpq.log.info('开始运行时间:'+qhcsj2)
g.stocks=["XAUUSD"]
hg.seemsg=假
g.hd=0.0001 #滑点比例
g.amount=0.01 #下单股数
g.i=0 #循环次数
g.hcl=0.25 #回撤率
g.zs=-0.011 #止损幅度
g.minp=0.0005 #保证最小获利
g.x=0.0012 #看多偏移
g.y=-0.0012 #看空偏移
g.multiple=2
g.magic=2
g.hh=1 #回合
g.sum_profit=0.0 #回合策略收益
输出(login)
如果 os.path.exists(filename):
#ans = input("发现配置文件,是否要载入(Y/N):")
ans='Y'
如果 ans=='Y' 或者 ans=="y":
gz=hmt5.loadm(filename)
输出(gz)
如果 len(gz)>0:
序列循环 code2,kind2,price2,volume2,magic2,sl2,tp2,comment2,condition2,count,stop,t,t2,x,y,d,p 在其中 gz:
cruise_missile.set_data(code2,kind2,price2,volume2,magic2,sl2,tp2,comment2,condition2,count,stop,t,t2,x,y,d,p)
输出("载入配置完成!")
否则:
输出('放弃载入配置。')
序列循环 symbol 在其中 g.stocks:
security=symbol
如果 security 不是 在其中 context.portfolio.positions:
context.portfolio.positions[security]=hpq.Position(security)
ask=hmt5.symbol_info_tick(symbol).ask
bid=hmt5.symbol_info_tick(symbol).bid
'''
kind种类,code代码,price价格,volume数量,
kind=0 #买多,固定价格
kind=1 #卖空,固定价格
kind=2 #买多,浮动价格
kind=3 #卖空,浮动价格
x是正涨幅
y是负涨幅
'''
#获取全部订单
df=hmt5.reload_positions2(magic=g.magic)
如果 len(df)>0:
fff=df.profit.sum() #总多空利润
vsum=df.volume.sum() #多空总单量
df_0=df[df.type==0] #多总持仓
df_1=df[df.type==1] #空总持仓
fff_0=df_0.profit.sum() #多总盈利
fff_1=df_1.profit.sum() #空总盈利
vvv_0=df_0.volume.sum() #多总单量
vvv_1=df_1.volume.sum() #空总单量
ask=hmt5.symbol_info_tick(security).ask
bid=hmt5.symbol_info_tick(security).bid
#多方跟踪
如果 (不是 cruise_missile.isin(security,2)) 并且 vvv_0==0:
cruise_missile.add(code=security,kind=2,price=ask,volume=g.amount,x=g.x,y=g.y,magic=g.magic)
#空方跟踪
如果 (不是 cruise_missile.isin(security,3)) 并且 vvv_1==0:
cruise_missile.add(code=security,kind=3,price=bid,volume=g.amount,x=g.x,y=g.y,magic=g.magic)
# 每个单位时间(如果按天回测,则每天调用一次,如果按分钟,则每分钟调用一次)调用一次
函数 开盘中(context):
#cruise_missile.clear()
条件循环 hg.istrade:
start = time.time()
g.i=g.i+1
security=g.stocks[0]
#获取用户登陆信息
accountinfo=mt5.account_info()
姓名=accountinfo.name
服务器=accountinfo.server
货币=accountinfo.currency
用户名=accountinfo.login
结余=accountinfo.balance
总净值=accountinfo.equity
总盈亏=accountinfo.profit
# print()
# print('----------用户信息----------')
# print('姓名:',姓名)
# print('服务器:',服务器)
# print('用户名',用户名)
# print('总盈亏',总盈亏)
# print('总净值',总净值)
# print('结余:',结余)
ask=hmt5.symbol_info_tick(security).ask
bid=hmt5.symbol_info_tick(security).bid
#获取全部订单
df=hmt5.reload_positions2(magic=g.magic)
fff=0.0
fff_0=0.0
fff_1=0.0
vvv_0=0.0
vvv_1=0.0
p_0=ask
p_1=bid
如果 len(df)>0:
fff=df.profit.sum() #总多空利润
vsum=df.volume.sum() #多空总单量
df_0=df[df.type==0] #多总持仓
df_1=df[df.type==1] #空总持仓
fff_0=df_0.profit.sum() #多总盈利
fff_1=df_1.profit.sum() #空总盈利
vvv_0=df_0.volume.sum() #多总单量
vvv_1=df_1.volume.sum() #空总单量
p_0=df_0.price_open.min()
p_1=df_1.price_open.max()
如果 (fff>20*(1+vsum*2.5) 并且 len(df_0)>0 并且 len(df_1)>0):
输出('总平仓')
hmt5.quanqing(magic=g.magic,comment2="quanqing")
cruise_missile.clear()
vvv_0=0
vvv_1=0
g.sum_profit=0.0
g.hh=g.hh+1
如果 (不是 cruise_missile.isin(security,2)) 并且 (不是 cruise_missile.isin(security,3)) 并且 len(df)==0:
g.sum_profit=0.0
g.hh=g.hh+1
#多方跟踪
如果 (不是 cruise_missile.isin(security,2)) 并且 vvv_0==0:
cruise_missile.add(code=security,kind=2,price=ask,volume=g.amount,x=g.x,y=g.y,magic=g.magic)
#空方跟踪
如果 (不是 cruise_missile.isin(security,3)) 并且 vvv_1==0:
cruise_missile.add(code=security,kind=3,price=bid,volume=g.amount,x=g.x,y=g.y,magic=g.magic)
如果 (不是 cruise_missile.isin(security,2)) 并且 (不是 cruise_missile.isin(security,3)):
如果 (p_0-p_1)/ask > 2*g.x:
如果 vvv_0>vvv_1 并且 len(df_1)<2:
cruise_missile.add(code=security,kind=3,price=bid,volume=g.amount,x=g.x,y=g.y,magic=g.magic)
否则如果 len(df_0)<2:
cruise_missile.add(code=security,kind=2,price=ask,volume=g.amount,x=g.x,y=g.y,magic=g.magic)
如果 (g.i%900==0) :
输出(df)
输出(vvv_0,fff_0,p_0,ask)
输出(vvv_1,fff_1,p_1,bid)
dd=hmt5.reload_positions2(magic=g.magic)
如果 len(dd)>0:
l2=len(dd)
序列循环 j2 在其中 range(l2):
swap2=dd.at[j2,'swap']
tt2=dd.at[j2,'ticket']
pp2=dd.at[j2,'profit']+swap2
ty2=dd.at[j2,'type']
amos=vv2=dd.at[j2,'volume']
cc2=dd.at[j2,'comment'].strip()
acc_avg_cost=op2=dd.at[j2,'price_open']
mg2=dd.at[j2,'magic']
security=sy2=dd.at[j2,'symbol']
tm2=dd.at[j2,'time']
ask=hmt5.symbol_info_tick(sy2).ask
bid=hmt5.symbol_info_tick(sy2).bid
#做止盈和止损处理
如果 ty2==0:
sell=hf.autosell(tt2,price=bid,cost=acc_avg_cost,withdraw=g.hcl,stoploss=g.zs,minp=g.minp,t=999) #追踪收盘价
如果 sell==2: #止损
g.sum_profit=g.sum_profit+pp2
p5=bid
x=order(security,amos,side='long',p=p5)
hmt5.pingcang(tt2,comment2="ping duo")
hpq.log.info(context.current_dt+ " 多单止损: %s ,数量:%d,卖出价格:%.2f,成交资金:%0.2f"%(security,amos,p5,amos*p5))
如果 amos==g.amount:
cruise_missile.add(code=security,kind=2,price=ask*(1-g.x/2),volume=g.amount,x=g.x,y=g.y,magic=g.magic)
否则如果 sell==1: #止盈
g.sum_profit=g.sum_profit+pp2
p5=bid
x=order(security,amos,side='long',p=p5)
hmt5.pingcang(tt2,comment2="ping duo")
hpq.log.info(context.current_dt+ " 多单止盈: %s ,数量:%d,卖出价格:%.2f,成交资金:%0.2f"%(security,amos,p5,amos*p5))
如果 amos==g.amount:
cruise_missile.add(code=security,kind=2,price=ask*(1-g.x/2),volume=g.amount,x=g.x,y=g.y,magic=g.magic)
如果 ty2==1:
buy=hf.autobuy(tt2,price=ask,cost=acc_avg_cost,withdraw=g.hcl,stoploss=g.zs,minp=g.minp,t=999) #追踪收盘价
如果 buy==2: #止损
g.sum_profit=g.sum_profit+pp2
p5=ask
x=order(security,amos,side='short',p=p5)
hmt5.pingcang(tt2,comment2="ping kong")
hpq.log.info(context.current_dt+ " 空单止损: %s ,数量:%d,卖出价格:%.2f,成交资金:%0.2f"%(security,amos,p5,amos*p5))
如果 amos==g.amount:
cruise_missile.add(code=security,kind=3,price=bid*(1+g.y/2),volume=g.amount,x=g.x,y=g.y,magic=g.magic)
否则如果 buy==1: #止盈
g.sum_profit=g.sum_profit+pp2
p5=ask
x=order(security,amos,side='short',p=p5)
hmt5.pingcang(tt2,comment2="ping kong")
hpq.log.info(context.current_dt+ " 空单止盈: %s ,数量:%d,卖出价格:%.2f,成交资金:%0.2f"%(security,amos,p5,amos*p5))
如果 amos==g.amount:
cruise_missile.add(code=security,kind=3,price=bid*(1+g.y/2),volume=g.amount,x=g.x,y=g.y,magic=g.magic)
如果 sy2 不是 在其中 context.portfolio.positions:
context.portfolio.positions[sy2]=hpq.Position(sy2)
context.portfolio.positions[sy2].total_amount=vv2
context.portfolio.positions[sy2].closeable_amount=vv2
context.portfolio.positions[sy2].acc_avg_cost=op2
context.portfolio.positions[sy2].value=op2*vv2
context.portfolio.positions[sy2].ticket=tt2
序列循环 symbol 在其中 g.stocks:
security=symbol
如果 security 不是 在其中 context.portfolio.positions:
context.portfolio.positions[security]=hpq.Position(security)
ask=hmt5.symbol_info_tick(symbol).ask
bid=hmt5.symbol_info_tick(symbol).bid
点差=ask-bid
##获取行情
rates= mt5.copy_rates_from_pos(symbol, mt5.TIMEFRAME_M1, 0, 1000)
data2=hmt5.tohpdata(rates)
nowtime=data2['time2'].iloc[-1]
#小白量化数据格式化
df=data2.reset_index(level=空, drop=真 ,col_level=0, col_fill='')
mydf=gs.initmydf(df) ##初始化mydf表
#对数据做小白量化各式转换
C=CLOSE=mydf['close']
L=LOW=mydf['low']
H=HIGH=mydf['high']
O=OPEN=mydf['open']
price = C.iloc[-1]
high= H.iloc[-1]
low= L.iloc[-1]
pre_close=C.iloc[-2] #前收盘
FD=HHV(H,80)-LLV(L,80)
TJ1=IF(FD>7,1,0)
acc_avg_cost = context.portfolio.positions[security].acc_avg_cost #买入成本价
amos=context.portfolio.positions[security].closeable_amount #可卖数量
amos2=context.portfolio.positions[security].total_amount #总数量
buy=cruise_missile.oncheck(security,2,ask)
amount=g.amount
如果 buy==1 :
price2=round(price*(1+g.hd),2)
x=order(security,g.amount,p=price2)
如果 vvv_1>vvv_0:
vvv_2=(vvv_1-vvv_0)/g.amount
如果 vvv_2<6:
amount=g.amount*int(1+vvv_2*g.multiple)
否则:
amount=vvv_2+1
dda=hmt5.buy(symbol =security,volume=amount,magic=g.magic,comment='b')
如果 x !=空:
hpq.log.info(context.current_dt+" 开多: %s ,数量:%d,买入价格:%.2f,成交资金:%0.2f"%(security,x.amount,price,x.amount*price))
amount=g.amount
sell=cruise_missile.oncheck(security,3,bid)
如果 sell==1:
price2=round(price*(1-g.hd),2)
x=order(security,0,p=price2)
如果 vvv_0>vvv_1:
amount=g.amount*int(1+(vvv_0-vvv_1)/g.amount*g.multiple)
vvv_2=(vvv_0-vvv_1)/g.amount
如果 vvv_2<6:
amount=g.amount*int(1+vvv_2*g.multiple)
否则:
amount=vvv_2+1
ddb=hmt5.sell(symbol =security,volume=amount,magic=g.magic,comment='s')
如果 x !=空:
hpq.log.info(context.current_dt+" 开空: %s ,数量:%d,买入价格:%.2f,成交资金:%0.2f"%(security,x.amount,price,x.amount*price))
end=time.time() #获取循环结束时间
如果 (g.i%900==0) :
gz=[]
data2=cruise_missile.get_data(security,2)
如果 len(data2)>0:
gz.append(data2)
data3=cruise_missile.get_data(security,3)
如果 len(data3)>0:
gz.append(data3)
如果 (g.i%2000==0) :
hmt5.savem(filename2,gz)
输出('保存文件:',filename2)
输出(g.hh,g.sum_profit)
输出('时间:',round(start,2),round(end,2),round(end-start,4),'秒,每秒跑%d圈。'%int(1/(end-start+0.000000001)))
data=cruise_missile.get_data(security,2)
如果 len(data)>0:
输出(data)
输出(price-data[2])
data=cruise_missile.get_data(security,3)
如果 len(data)>0:
输出(data)
输出(price-data[2])
上图是每秒计算100次的超高频运算。用1000美元1天赚钱1300美元。
当然这有运气成分。如果遇到行情上下轨道逐步加长,且策略无法盈利,也会出现因止损而亏损。
穿云箭量化平台提供了3中指标公式源码运行模块,用户可以直接使用指标公式源码写自动交易策略。
超越自己是我的每一步!我的进步就是你的进步!