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