VeighNa量化社区
你的开源社区量化交易平台
Member
avatar
加入于:
帖子: 103
声望: 7

`from datetime import datetime
from typing import Any
import time
import numpy as np
from sqlalchemy import false
from vnpy.trader.constant import Offset, Direction, Status
from vnpy_ctastrategy import (
CtaTemplate,
StopOrder,
TickData,
BarData,
TradeData,
OrderData,
BarGenerator,
ArrayManager,
)

class Macd_Ma_sjc_tick(CtaTemplate):
""""""

#开发都姓名
author = "LI CHUNBAO"
strategy_name = "MACD双金叉"
#定义参数
fast_window = 20
slow_window = 40
fixed_size = 1 #交易手数
period = 5


#定义变量
open_pos = None
shut_pos = None
buy_price = 0
sell_price = 0
short_price = 0
cover_price = 0
Stop_loss_long = 0 # 多头止损价格
Stop_loss_short = 0 # 空头止损价格
profit_loss = 0


#添加参数和变量到对应的列表
parameters = [
    "fast_window",
    "slow_window",
    "fixed_size",
    "period",
    ]

variables = [
    "buy_price",
    "sell_price",
    "short_price",
    "cover_price",
    "profit_loss"
    ]

def __init__(
    self,
    cta_engine: Any,
    strategy_name: str,
    vt_symbol: str,
    setting: dict,
):
    """"""
    super().__init__(cta_engine,strategy_name,vt_symbol,setting)
    self.bid_price1 = 0
    self.ask_price1 = 0
    self.buy_vt_orderids = []
    self.sell_vt_orderids = []
    self.short_vt_orderids = []
    self.cover_vt_orderids = []
    self.buy_signal = False
    self.sell_signal = False
    self.short_signal = False
    self.cover_signal = False
    self.active_order = False
    self.cha_array: np.ndarray = np.zeros(2) 

    self.bg = BarGenerator(self.on_bar,self.period,self.on_period_min_bar)
    self.am = ArrayManager()

def on_init(self):
    """
    Callback when strategy is inited.
    """  
    self.write_log("策略初始化")
    self.load_bar(30)
    if not self.am.inited:
        self.write_log("数据不足,未能完成策略初始化")  
def on_start(self):
    """
    Callback when strategy is started.
    """
    self.write_log("策略启动")
    self.put_event()    
def on_stop(self):
    """
    Callback when strategy is stopped.
    """
    self.write_log("策略停止")
    self.put_event()    
def on_tick(self, tick: TickData):
    """
    Callback of new tick data update.
    """        
    self.bg.update_tick(tick)      

def on_bar(self, bar: BarData):
    """
    Callback of new bar data update.
    """
    self.bg.update_bar(bar)
    if self.pos == 0:
        # 检查之前委托都已经结束
        if not self.buy_vt_orderids:
            # 检查存在信号
            if self.buy_signal:
                self.buy_vt_orderids = self.buy(bar.open_price + 5, self.fixed_size) #买入开仓
                self.write_log(f"开多")
                # print(f"开多{bar.datetime}")
                self.buy_signal = False
        else:                
            # 遍历委托号列表撤单
            for vt_orderid in self.buy_vt_orderids:
                self.cancel_order(vt_orderid)
        if not self.short_vt_orderids:
            if self.short_signal:
                self.short_vt_orderids = self.short(bar.open_price - 5,self.fixed_size) #卖出开仓
                self.write_log(f"开空")
                # print(f"开空{bar.datetime}")
                self.short_signal = False
        else:
            for vt_orderid in self.short_vt_orderids:
                self.cancel_order(vt_orderid)
    elif self.pos > 0:
        if not self.sell_vt_orderids:
            if self.sell_signal:
                self.sell_vt_orderids = self.sell(bar.open_price - 5, abs(self.pos)) #卖出平仓
                self.write_log(f"卖平") 
                self.sell_signal = False
                self.short_vt_orderids = self.short(bar.open_price - 5,self.fixed_size) #卖出开仓
                self.write_log(f"反手开空")
        else:
            for vt_orderid in self.sell_vt_orderids:
                self.cancel_order(vt_orderid)

    elif self.pos < 0:
        if not self.cover_vt_orderids:
            if self.cover_signal:
                self.cover_vt_orderids = self.cover(bar.open_price + 5, abs(self.pos)) #买入平仓
                self.write_log(f"买平")
                self.cover_signal = False
                self.buy_vt_orderids = self.buy(bar.open_price + 5, self.fixed_size) #买入开仓
                self.write_log(f"反手开多")
        else:
            for vt_orderid in self.cover_vt_orderids:
                self.cancel_order(vt_orderid)

    if abs(self.pos)>1:
        print(f"{bar.datetime} 仓位:{self.pos}")

    self.put_event()
def on_period_min_bar(self,bar:BarData):
    """period回调函数"""        
    self.am.update_bar(bar)
    if not self.am.inited:
        return        

    # 判断MA交叉
    fast_ma = self.am.sma(self.fast_window,array=True)
    fast_ma_1 =fast_ma[-1] 
    fast_ma_0 =fast_ma[-2]
    slow_ma = self.am.sma(self.slow_window,array=True)
    slow_ma_1 =slow_ma[-1] 
    slow_ma_0 =slow_ma[-2]        
    cross_over_ma = (fast_ma_1 >= slow_ma_1 and fast_ma_0 < slow_ma_0) #金叉                        
    cross_below_ma = (fast_ma_1 <= slow_ma_1 and fast_ma_0 > slow_ma_0)#死叉                        

    # 判断MACD交叉
    DIFF,DEA,MACD= self.am.macd(12,26,9,array=True)
    DIFF_1 = DIFF[-1]
    DIFF_0 = DIFF[-2]
    DEA_1 = DEA[-1]
    DEA_0 = DEA[-2]

    cross_over_macd = (DIFF_1 >= DEA_1 and DIFF_0 < DEA_0) #金叉
    cross_below_macd = (DIFF_1 <= DEA_1 and DIFF_0 > DEA_0)#死叉

    # 统计macd和ma双交叉情况               
    if cross_over_ma:
        self.cha_array[:-1] = self.cha_array[1:]
        self.cha_array[-1] = 1
    elif cross_below_ma:
        self.cha_array[:-1] = self.cha_array[1:]
        self.cha_array[-1] = -1
    if cross_over_macd:
        self.cha_array[:-1] = self.cha_array[1:]
        self.cha_array[-1] = 1
    elif cross_below_macd:
        self.cha_array[:-1] = self.cha_array[1:]
        self.cha_array[-1] = -1
    # print(f"时间:{bar.datetime} {self.cha_array}")   

    # 生成开平仓交易信号
    if self.cha_array.sum()>= 2:
        # print(f"{bar.datetime}两金叉")
        #缓存止损价格
        self.Stop_loss_long = bar.low_price
        if self.pos == 0:
            self.buy_signal = True
            self.sell_signal = False
            self.short_signal = False
            self.cover_signal = False 
        elif self.pos < 0:
            self.buy_signal = False
            self.sell_signal = False
            self.short_signal = False
            self.cover_signal = True
        self.cha_array = np.zeros(2)
    elif self.cha_array.sum() <= -2:
        # print(f"{bar.datetime}双死叉")
        #缓存止损价格
        self.Stop_loss_short = bar.high_price
        if self.pos == 0:
            self.buy_signal = False
            self.sell_signal = False
            self.short_signal = True
            self.cover_signal = False
        elif self.pos > 0:
            self.buy_signal = False
            self.sell_signal = True
            self.short_signal = False
            self.cover_signal = False
        self.cha_array = np.zeros(2)
    self.put_event()
def on_trade(self, trade: TradeData):
    """
    Callback of new trade data update.
    """        
    #记录开平仓价格,并统计利润点数。
    if trade.offset == Offset.OPEN:
        if trade.direction == Direction.LONG:
            self.buy_price = trade.price
            self.sell(self.Stop_loss_long,abs(self.pos),stop=True)
        elif trade.direction == Direction.SHORT:
            self.short_price = trade.price
            self.cover(self.Stop_loss_short,abs(self.pos),stop=True)
    elif trade.offset == Offset.CLOSETODAY or trade.offset == Offset.CLOSEYESTERDAY or trade.offset == Offset.CLOSE:
        if trade.direction == Direction.LONG:
            self.cover_price = trade.price
            a = self.short_price - self.cover_price
            self.profit_loss += a
        elif trade.direction == Direction.SHORT:
            self.sell_price = trade.price
            b = self.sell_price - self.buy_price   
            self.profit_loss += b

    # self.active_order = False
    # msg = f"新的成交, 策略{self.strategy_name}, 方向{trade.direction}, 开平{trade.offset}, 当前仓位{self.pos},当前盈亏{self.profit_loss}"
    # self.send_email(msg)
    self.put_event()    
def on_order(self, order: OrderData):
    """
    Callback of new order data update.    
    """
    if order.status == Status.SUBMITTING:
        # self.active_order = True
        return
    for buf_orderids in [
        self.buy_vt_orderids,
        self.sell_vt_orderids,
        self.short_vt_orderids,
        self.cover_vt_orderids
    ]:
        if order.vt_orderid in buf_orderids:
            buf_orderids.remove(order.vt_orderid)
    # self.active_order = False
    self.put_event()
def on_stop_order(self, stop_order: StopOrder):
    """
    Callback of stop order update.
    """
    pass`

以上是策略的完整代码,为什么我使用停止单后,仓位出现了这个结果(如下图所示)

description

逻辑上我的仓位只有三种可能:0、1、-1,加上停止单止损后,却出现了2和-2的情况。这是为什么?

Member
avatar
加入于:
帖子: 4622
声望: 284

可以自己结合策略逻辑和委托成交记录排查看看

Member
avatar
加入于:
帖子: 716
声望: 62

你可以在on_orderhe on_trader下的每一个判断中打印一次,这样可以检查一下,成交的订单和委托的订单是否一致。你好像在下单之前没有撤销之前的委托,有可能是在未成交的情况下连续开仓造成的

Member
avatar
加入于:
帖子: 103
声望: 7

郭易燔 wrote:

你可以在on_orderhe on_trader下的每一个判断中打印一次,这样可以检查一下,成交的订单和委托的订单是否一致。你好像在下单之前没有撤销之前的委托,有可能是在未成交的情况下连续开仓造成的
谢谢

© 2015-2022 上海韦纳软件科技有限公司
备案服务号:沪ICP备18006526号

沪公网安备 31011502017034号

【用户协议】
【隐私政策】
【免责条款】