网格交易 python_VNPY网格交易法优化

from vnpy.app.cta_strategy import (

CtaTemplate,

StopOrder,

TickData,

BarData,

TradeData,

OrderData,

BarGenerator,

ArrayManager,

)

import sys,os

import json

from pathlib import Path

class GridDemo(CtaTemplate):

Lot = 1 #默认手数

grid_ma_length = 30 #均线周期

grid_step = 5 #止损步长

Lot_max = 233 #最大手数

grid_ma = 0 #均线

parameters = ["Lot",

"grid_ma_length",

"grid_step",

'Lot_max'

]

variables = ["grid_ma"]

def __init__(self, cta_engine, strategy_name, vt_symbol, setting):

""""""

super().__init__(cta_engine, strategy_name, vt_symbol, setting)

self.bg = BarGenerator(self.on_bar)

self.am = ArrayManager()

self.ask_price = 0.0 #买入价

self.bid_price = 0.0 #卖出价

self.traded = [] #成交记录

self.kai = True #开平

self.fangxiang = '' #买卖

p=Path(os.getcwd()+'\logs')

p.mkdir(exist_ok=True) #新建目录,如果目录已存在,则不会引起错误

#由于文件目录一样,如果采用新策略、新品种,本地成交记录必须先删除,否则会影响初始交易手数

if os.path.isfile(os.getcwd()+'\logs\KaiLog.json') != True: #文件不存在则创建文件,创建完关闭

with open(os.getcwd()+'\logs\KaiLog.json','w+',encoding='utf-8') as Kai_Log:

json.dump([],Kai_Log) #文件不存在创建,序列化为列表,然后关闭

self.Kai_Log=open(os.getcwd()+'\logs\KaiLog.json','r+',encoding='utf-8') #先读后写再次打开新建的文件

else : self.Kai_Log=open(os.getcwd()+'\logs\KaiLog.json','r+',encoding='utf-8') #文件存在则先读后写。文件写入完后要close()关闭才会从缓存保存进文件

if os.path.isfile(os.getcwd()+'\logs\PingLog.json') != True: #文件不存在则创建文件,创建完关闭

with open(os.getcwd()+'\logs\PingLog.json','w+',encoding='utf-8') as Ping_Log:

json.dump([],Ping_Log) #文件不存在创建,序列化为列表,然后关闭

self.Ping_Log=open(os.getcwd()+'\logs\PingLog.json','r+',encoding='utf-8') #先读后写再次打开新建的文件

else : self.Ping_Log=open(os.getcwd()+'\logs\PingLog.json','r+',encoding='utf-8') #文件存在则先读后写。文件写入完后要close()关闭才会从缓存保存进文件

self.kai_list = json.load(self.Kai_Log) #文件读取进列表

self.ping_list = json.load(self.Ping_Log)

def on_init(self):

"""Callback when strategy is inited."""

self.write_log("策略初始化")

self.load_bar(self.grid_ma_length)

def on_start(self):

"""Callback when strategy is started."""

self.write_log("策略启动")

def on_stop(self):

"""Callback when strategy is stopped."""

self.write_log("策略停止")

def on_tick(self, tick: TickData):

"""Callback of new tick data update."""

self.bg.update_tick(tick)

#self.ask_price = tick.ask_price_1 #买卖价取tick对手价,盘中以最新行情判断交易,则将交易逻辑写在on_tick中

#self.bid_price = tick.bid_price_1

def on_bar(self, bar: BarData): #每分钟K走完调用一次

"""Callback of new bar data update."""

'''下单逻辑:空仓时开仓,有仓时平仓;止损点数=grid_step,止盈点数=2*grid_step;策略分析:价格偏离均值时有向均值回归的倾向,所以:最新价(对手价) - 均值 > grid_step,做空,反之做多若不等K线走完,用最新盘口行情,则把逻辑写在on_tick函数中该策略分析较为简单,可以改成其他策略,但下单逻辑不能改'''

self.cancel_all()

am = self.am #转换为内部变量,增加查询速度

am.update_bar(bar) #m默认生成1分钟数据

if not am.inited:

return

grid_array = am.sma(self.grid_ma_length, array=True) #计算均线

self.grid_ma = grid_array[-1] #取均线最新值

self.ask_price = bar.close_price #买卖价取K线收盘价

self.bid_price = bar.close_price

#self.write_log('price'+str(self.ask_price))

#self.write_log('grid_ma'+str(self.grid_ma))

lots = self.shoushu(Lots=self.Lot) #计算开仓手数

if lots >= self.Lot_max : lots = self.Lot_max

#self.write_log('shoushu: '+str(lots))

#self.write_log('grid_step: '+str(self.grid_step))

#pos配置在本地文件cta_strategy_data.json中,只能通过策略更改,外部下单不会修改

if self.pos == 0 :

if self.grid_ma - self.ask_price >= self.grid_step:

#stop为True是本地停止单,这个停止单并没有发送给交易所,而是存储在内部,使用ctaEngine.sendStopOrder()函数; 否则这直接发送到交易所,使用ctaEngine.sendOrder函数

#对于StopOrder真正触发的交易通常是涨停价或者跌停价发出的市价单(Market price),参数price只是触发条件;而普通sendOrder是真正按照参数price的限价单(Limit price)

vt_orderid = self.buy(price=self.ask_price, volume=lots,stop=False,lock=False)

self.fangxiang = 'Buy'

elif self.bid_price - self.grid_ma >= self.grid_step:

vt_orderid = self.short(price=self.bid_price, volume=lots,stop=False,lock=False)

self.fangxiang = 'Sell'

self.kai = True

elif self.pos < 0 :

if self.ask_price - self.kai_list[-1]['price'] >= self.grid_step :

vt_orderid = self.cover(price=self.ask_price, volume=abs(self.pos),stop=False,lock=False)

elif self.kai_list[-1]['price'] - self.ask_price >= self.grid_step * 2 :

vt_orderid = self.cover(price=self.ask_price, volume=abs(self.pos),stop=False,lock=False)

self.kai = False

elif self.pos > 0 :

if self.bid_price - self.kai_list[-1]['price'] >= self.grid_step * 2 :

vt_orderid = self.sell(price=self.bid_price, volume=self.pos,stop=False,lock=False)

elif self.kai_list[-1]['price'] - self.bid_price >= self.grid_step :

vt_orderid = self.sell(price=self.bid_price, volume=self.pos,stop=False,lock=False)

self.kai = False

self.put_event()

def on_order(self, order: OrderData):

"""Callback of new order data update."""

pass

def on_trade(self, trade: TradeData): #每笔成交调用一次

"""Callback of new trade data update."""

self.write_log(trade)

#shoshu = 0

jiage = 0.0

if self.kai:

tr_dic = {'symbol':trade.symbol,'volume':trade.volume,'price':trade.price,'datetime':str(trade.datetime)}

self.kai_list.append(tr_dic)

self.Kai_Log.seek(0) #把操作标记移到0

self.Kai_Log.truncate()

json.dump(self.kai_list, self.Kai_Log) #把当日开仓成交记录写入缓存

self.Kai_Log.flush() #实时写入本地文件

elif not self.kai :

if self.fangxiang == 'Buy' : jiage = trade.price - self.kai_list[-1]['price']

elif self.fangxiang == 'Sell' : jiage = self.kai_list[-1]['price'] - trade.price

tr_dic = {'symbol':trade.symbol,'volume':trade.volume,'price':trade.price,'lirun':jiage,'datetime':str(trade.datetime)}

self.ping_list.append(tr_dic)

self.Ping_Log.seek(0) #把操作标记移到0

self.Ping_Log.truncate()

json.dump(self.ping_list, self.Ping_Log) #把当日开仓成交记录写入缓存

self.Ping_Log.flush()

self.put_event()

def on_stop_order(self, stop_order: StopOrder):

"""Callback of stop order update."""

pass

def shoushu(self,Lots=1): #如果采用新策略、新品种,本地成交记录必须先删除,否则会影响初始交易手数

try:

if self.ping_list[-1]['lirun'] > 0: #前一单盈利,开仓手数默认

Lots = self.Lot

elif self.ping_list[-2]['lirun'] > 0: #前二单盈利,开仓手数默认

Lots = self.Lot

else :

Lots = self.ping_list[-1]['volume'] + self.ping_list[-2]['volume'] #前一二单亏损,开仓手数为两单之和

except IndexError:

Lots = self.Lot #没有平仓记录或只有一个平仓记录且亏损,开仓手数默认

return Lots

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值