用python寫期貨量化策略,期貨單品種MACD擇時加ATR止損

import numpy as np
import talib
import time
import jqdata
import talib
import smtplib
from email.mime.text import MIMEText
from email.header import Header

## 初始化函數,設定基準等等
def initialize(context):
    #上海期貨交易所產品
    '''AG8888.XSGE	白銀期貨指數	PB8888.XSGE	鉛期貨指數
    AU8888.XSGE	黃金期貨指數	RB8888.XSGE	螺紋鋼期貨指數
    AL8888.XSGE	鋁期貨指數	RU8888.XSGE	天然橡膠期貨指數
    BU8888.XSGE	石油瀝青期貨指數	SN8888.XSGE	錫期貨指數
    CU8888.XSGE	銅期貨指數	WR8888.XSGE	線材期貨指數
    FU8888.XSGE	燃料油期貨指數	ZN8888.XSGE	鋅期貨指數
    HC8888.XSGE	熱軋卷板期貨指數	NI8888.XSGE	鎳期貨指數
    SP8888.XSGE	紙漿主力合約		
    '''
    g.stockkind='AG'
    g.stockcode=str('AG9999.XSGE')
    #g.stockkind='AU'
    #g.stockkind='RB'
    
    # 設定XX期貨作爲基準
    set_benchmark('AG9999.XSGE')
    # 開啓動態復權模式(真實價格)
    set_option('use_real_price', True)
    # 過濾掉order系列API產生的比error級別低的log
    # log.set_level('order', 'error')
    # 輸出內容到日誌 log.info()
    log.info('初始函數開始運行且全局只運行一次')
    
    # 開盤前運行
    run_daily( before_market_open, time='09:00', reference_security='AG9999.XSGE')
    
    ### 期貨相關設定 ###
    # 設定賬戶爲金融賬戶
    set_subportfolios([SubPortfolioConfig(cash=context.portfolio.starting_cash, type='index_futures')])
    # 期貨類每筆交易時的手續費是:買入時萬分之0.23,賣出時萬分之0.23,平今倉爲萬分之23
    set_order_cost(OrderCost(open_commission=0.000023, close_commission=0.000023,close_today_commission=0.0023), type='index_futures')
    # 設定保證金比例
    set_option('futures_margin_rate', 0.15)

    # 設置期貨交易的滑點
    set_slippage(StepRelatedSlippage(2))
    # 運行函數(reference_security爲運行時間的參考標的;傳入的標的只做種類區分,因此傳入'IF8888.CCFX'或'IH1602.CCFX'是一樣的)
    # 注意:before_open/open/close/after_close等相對時間不可用於有夜盤的交易品種,有夜盤的交易品種請指定絕對時間(如9:30)
    


 
## 開盤前運行函數
def before_market_open(context):

    # 輸出運行時間
    log.info('函數運行時間(before_market_open):'+str(context.current_dt.time()))

    # 給微信發送消息(添加模擬交易,並綁定微信生效)
    # send_message('美好的一天~')
    #stocklist=[]
    ## 獲取主力合約
    g.domin=get_dominant_future(g.stockkind, date=context.previous_date)
    print (g.domin)
    
    #買入信號
    g.sign=0
    #當日清倉標誌
    g.clear=0

## 開盤時運行函數
def handle_data(context,data):
    
    log.info('函數運行時間(market_open):'+str(context.current_dt.time()))
    
    timeArray = context.current_dt.time().strftime('%H:%M:%S')
    #timeArray = time.strptime(context.current_dt.time(), "%H:%M:%S")
    clocktime=int(str(timeArray)[-5:-3])
    
    if clocktime % 5 == 0:  
        deal(context)
    else:
        pass
    
    

def deal(context):
    ## 交易

    # 獲取當月合約交割日期
    end_data = get_CCFX_end_date(g.domin)
    
    
    #判斷g.sign  做macd交易判斷
    df=get_price(g.stockcode ,count=40, end_date=context.current_dt, frequency='15m',fields='close')
    df2=get_price(g.stockcode ,count=40, end_date=context.current_dt, frequency='60m',fields='close')
    df3=get_price(g.stockcode ,count=40, end_date=context.current_dt, frequency='240m',fields='close')
    df4=get_price(g.stockcode ,count=40, end_date=context.current_dt, frequency='1d',fields='close')
    macd_15min=macd(df['close'])[0]
    
    macd_60min=macd(df2['close'])[0]
    macd_1h=macd_60min
    macd_4h=macd(df3['close'])[0]
    macd_4h_diff=macd(df3['close'])[1]
    macd_4h_dea=macd(df3['close'])[2]
    macd_1d=macd(df4['close'])[0]
    
    #print (macd_15min)
    #print (macd_60min)
    

    #止損清倉判斷
    if tralling_stop(context, g.stockcode)==1:
        #止損多頭
        order_target(g.domin, 0, side='long')
        g.sign=0
        g.clear=1
        
    elif tralling_stop(context, g.stockcode)==-1:
        
        #止損空頭
        order_target(g.domin, 0, side='short')
        g.sign=0
        g.clear=-1
    
    #開倉同時保證自己當日沒有過當前方向的清倉
    '''
    if macd_15min[-1]>0 and macd_15min[-2]<=0 and macd_60min[-1]>0 and g.clear<1:
        g.sign=1
    elif  macd_15min[-1]<0 and macd_15min[-2]>=0 and macd_60min[-1]<0 and g.clear>-1:
        g.sign=-1
    '''
    '''
    if macd_1h[-1]>0 and macd_1h[-2]<=0 and macd_1d[-1]>0 and g.clear<1:
        g.sign=1
    elif  macd_1h[-1]<0 and macd_1h[-2]>=0 and macd_1d[-1]<0 and g.clear>-1:
        g.sign=-1
        
    '''
    #單純macd
    if macd_4h[-1]>0>macd_4h[-2] and macd_4h_diff[-1]>0 and macd_4h_dea[-1]>0:
        g.sign=1
    elif macd_4h[-1]<0<macd_4h[-2]and macd_4h_diff[-1]<0 and macd_4h_dea[-1]<0:
        g.sign=-1
        
    
    

    # 判斷當月合約交割日當天不開倉,多頭交易
    if (g.sign==1):
        if (context.current_dt.date() == end_data):
            
            pass
        else:
            #如果空倉>=0,開多倉
            if (len(context.portfolio.short_positions) >= 0 and len(context.portfolio.long_positions) == 0):
                log.info('開多倉---:')
                
                if len(context.portfolio.short_positions) >0 :
                    # 平倉空頭
                    order_target(g.domin, 0, side='short')
       
                # 做多頭合約
                print('開多頭合約')
                if context.portfolio.available_cash>3500:
                    order_value(g.domin, 0.9*context.portfolio.available_cash , side='long')
                    g.sign=1
                else:
                    print ('沒錢開倉')
                

                
    #空頭交易
    if (g.sign == -1):
        if (context.current_dt.date() == end_data):
            # return
            pass
        else:
            #如果多倉>=0,開空倉
            if (len(context.portfolio.short_positions) >= 0 and len(context.portfolio.long_positions) == 0):
                log.info('開空倉---:')
                
                if len(context.portfolio.long_positions) >0 :
                    # 平倉多頭
                    order_target(g.domin, 0, side='long')
                # 開空頭合約
                print('開空頭合約')
                if context.portfolio.available_cash>3500:
                    order_value(g.domin, 0.9*context.portfolio.available_cash , side='short')
                    g.sign=-1
                else:
                    print ('沒錢開倉')
    else:
        pass


def fasong(message,targetmail):


    '''發送郵箱'''
    sender = '[email protected]' #企業263郵箱
    '''接收郵箱'''
    receiver = targetmail
    '''發送郵件主題'''
    subject = 'message stock'
    '''發送郵箱服務器'''
    smtpserver = 'smtp.163.com'
    '''發送郵箱用戶/密碼'''
    username = '[email protected]'
    password = 'XXXXX'
    '''中文需參數‘utf-8’ ,單字節字符不需要'''
    msg = MIMEText(message,'plain','utf-8')
    msg['Subject'] = Header(subject, 'utf-8')
    msg['From'] = 'XX<[email protected]>'
    msg['To'] = targetmail
    smtp = smtplib.SMTP()
    smtp.connect('smtp.163.com')
    smtp.login(username, password)
    smtp.sendmail(sender, receiver, msg.as_string())
    smtp.quit()
    print ("Email has been sent out!")   
    
    
########################## 獲取期貨合約信息,請保留 #################################
# 獲取金融期貨合約到期日
def get_CCFX_end_date(future_code):
    # 獲取金融期貨合約到期日
    return get_security_info(future_code).end_date
    
    
###############
def macd(close):
    macdDIFF, macdDEA, macd = talib.MACDEXT(close, fastperiod=12, fastmatype=1, slowperiod=26, slowmatype=1, signalperiod=9, signalmatype=1)
    macd = macd * 2
    list1=[macd,macdDIFF,macdDEA]
    return list1




def tralling_stop(context, stock_code):    
    ATR_timeperiod=14
    # 獲取stock_code股票的歷史數據
    Data_ATR=get_price(stock_code ,count=ATR_timeperiod+10, end_date=context.current_dt, frequency='15m',fields=['close','high','low'])
    close_ATR = Data_ATR['close']
    high_ATR = Data_ATR['high']
    low_ATR = Data_ATR['low']

    # 計算stock_code股票的AT
    atr = talib.ATR(high_ATR, low_ATR, close_ATR)
    highest20 = max(close_ATR[-20:])
    lowest20 = min(close_ATR[-20:])
    
      
    
    if ((highest20 - close_ATR[-1]) > (2*atr[-1])) and len(context.portfolio.long_positions) >0:
        print('ATR多頭止損')
        return 1
    elif ((close_ATR[-1] - lowest20 ) > (2*atr[-1])) and len(context.portfolio.short_positions) >0:
        print('ATR空頭止損')
        return -1
    else:
        return 0
    

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章