#encoding:gbk ''' 本策略读取文件order.csv,按照文件中内容进行交易。 ''' import pandas as pd import numpy as np import talib import csv def init(ContextInfo): #读取文件order.csv global order_smbol global order_ask global order_bid global order_stoploss path_order = 'C:/Users/mkdon/Documents/myCode/TradeStation/Order.csv' #path_order = './Order.csv' order_smbol = get_order_symbol(path_order) order_ask = get_dict_order(path_order, 'OFFER') order_bid = get_dict_order(path_order, 'BID') order_stoploss = get_dict_order(path_order, 'STOPLOSS') #设置账户 #ContextInfo.accID = '110002343279' ContextInfo.accID = '410015061413' #设置交易参数 ContextInfo.numberorders = 10 #20 ContextInfo.numbersOfSortedBid = 8 ContextInfo.stopLimit = 0.18 #止损点 ContextInfo.period1 = 5 #回测周期数1 ContextInfo.period2 = 10 #回测周期数2 ContextInfo.period_max = max(ContextInfo.period1, ContextInfo.period2) ContextInfo.ask_step = 0.005 #追踪卖出价格梯度 ContextInfo.bid_step = 0.005 #追踪买入价格梯度 ContextInfo.ask_delta = 0.002 #追踪卖出触发余量 ContextInfo.bid_delta = 0.002 #追踪买入触发余量 ContextInfo.max_buy_levels = 1 #5 #单只股票最多持有份数 ContextInfo.max_daily_buy_levels = 1 #3 #单只股票当日最多买入次数 ContextInfo.bid_pips = 0.0005 #买入价格梯度 ContextInfo.ask_pips = 0.0005 #卖出价格梯度 #获取可用持仓 ContextInfo.holdingsAvalable = get_holdingsAvalable(ContextInfo.accID,"stock") #获取持仓成本 ContextInfo.holdingsCost = get_holdingsCost(ContextInfo.accID,"stock") #获取买入清单 ContextInfo.buylist = get_buylist(order_smbol, order_bid, ContextInfo.numbersOfSortedBid) #获取持仓清单 ContextInfo.selllist = list(ContextInfo.holdingsAvalable.keys()) #获取交易清单 ContextInfo.trade_code_list = ContextInfo.selllist + ContextInfo.buylist #去除清单中的重复项 ContextInfo.trade_code_list = trim_list(ContextInfo.trade_code_list) #去除清单中的无效代码 #print(ContextInfo.trade_code_list) #设置股票池 ContextInfo.set_universe(ContextInfo.trade_code_list) #获取当前账户总资产 ContextInfo.accountvalue = get_accountvalue(ContextInfo.accID,"stock") #计算单位订单金额 ContextInfo.unitOrderValue = ContextInfo.accountvalue/ContextInfo.numberorders ContextInfo.unitOrderValue = int(ContextInfo.unitOrderValue * 0.01) * 100 print('账户资产总额:',ContextInfo.accountvalue) print('单位订单金额',ContextInfo.unitOrderValue) def handlebar(ContextInfo): if ContextInfo.is_last_bar(): #获取当前可用资金 cash = get_avaliablecash(ContextInfo.accID,"stock") cash = round(cash,2) #获取可用持仓 ContextInfo.holdingsAvalable = get_holdingsAvalable(ContextInfo.accID,"stock") #获取当前持仓 ContextInfo.holdings = get_holdings(ContextInfo.accID,"stock") #获取委托号 ContextInfo.orderID = get_orderID(ContextInfo.accID,"stock") #print(ContextInfo.orderID) #获取已成交委托号 ContextInfo.dealID = get_dealID(ContextInfo.accID,"stock") #print(ContextInfo.dealID) #获取历史价格 dict_hist = ContextInfo.get_history_data(ContextInfo.period_max,'tick','quoter') for s in range(len(ContextInfo.trade_code_list)): stockcode = ContextInfo.trade_code_list[s] #ret = ContextInfo.get_market_data(['quoter'], stock_code = [stockcode], period = 'tick', count = 5) list_hist = dict_hist[stockcode] if len(list_hist) == ContextInfo.period_max: dict_price = list_hist[ContextInfo.period_max - 1] dict_price1 = list_hist[ContextInfo.period_max - 1 - ContextInfo.period1] dict_price2 = list_hist[0] close = dict_price["lastPrice"] #最新价 close1 = dict_price1["lastPrice"] #回溯价1 close2 = dict_price2["lastPrice"] #回溯价2 #刷新追踪卖出价和追踪买入价 ask = order_ask[stockcode] bid = order_bid[stockcode] stoploss = order_stoploss[stockcode] ask = get_trailing_ask(ask, close, ContextInfo.ask_step) bid = get_trailing_bid(bid, close, ContextInfo.bid_step) order_ask[stockcode] = ask order_bid[stockcode] = bid #交易 if stockcode in ContextInfo.selllist: #如果有可用持仓 position = ContextInfo.holdings[stockcode] #获取当前持仓数量 positionAvalable = ContextInfo.holdingsAvalable[stockcode] #获取可用持仓数量 cost = ContextInfo.holdingsCost[stockcode] #获取持仓成本 #计算买入份数 positionAvalable_levels = get_positionAvalable_levels(positionAvalable, cost, ContextInfo.unitOrderValue) positionNew_levels = get_positionNew_levels(position, positionAvalable, close, ContextInfo.unitOrderValue) isUnderBuyLevels = positionAvalable_levels + positionNew_levels < ContextInfo.max_buy_levels and positionNew_levels < ContextInfo.max_daily_buy_levels #卖出操作 if positionAvalable > 0: print(stockcode,'可用持仓', 100 * positionAvalable) if Ready_to_stoploss(close, cost, stoploss, ContextInfo.stopLimit): #止损卖出 order_lots(stockcode,-positionAvalable,ContextInfo,ContextInfo.accID) elif close2 > close and close >= ask and close <= ask + get_delta_sell(ask, ContextInfo.ask_delta): position_sell = get_position_sell(positionAvalable, positionAvalable_levels) order_lots(stockcode,-position_sell,ContextInfo,ContextInfo.accID) print(stockcode,"卖出:", 100 * position_sell) #如果持仓份额未达到设定数量,执行买入操作 if isUnderBuyLevels: if cash > ContextInfo.unitOrderValue: #如果可用资金大于单位订单金额 print(stockcode,'待价买入') if close1 < close and close <= bid and close >= bid - get_delta_bid(bid, ContextInfo.bid_delta): cancel_buyorder(stockcode, ContextInfo, ContextInfo.accID) #取消以前买入委托 order_percent(stockcode, 1/ContextInfo.numberorders, ContextInfo, ContextInfo.accID) print(stockcode,"买入:", stockcode, close1, close, bid) else: print(stockcode,'可用资金',cash) else: #如果没有可用持仓, 执行买入操作 positionAvalable = 0 if stockcode in list(ContextInfo.holdings.keys()): #如果有持仓 position = ContextInfo.holdings[stockcode] #获取当前持仓数量 positionNew_levels = get_positionNew_levels(position, positionAvalable, close, ContextInfo.unitOrderValue) isUnderBuyLevels = positionNew_levels < ContextInfo.max_daily_buy_levels else: isUnderBuyLevels = True if isUnderBuyLevels: if cash > ContextInfo.unitOrderValue: #如果可用资金大于单位订单金额 print(stockcode,'待价买入') if close1 < close and close <= bid and close >= bid - get_delta_bid(bid, ContextInfo.bid_delta): cancel_buyorder(stockcode, ContextInfo, ContextInfo.accID) #取消以前买入委托 order_percent(stockcode, 1/ContextInfo.numberorders, ContextInfo, ContextInfo.accID) print(stockcode,"买入:", stockcode, close1, close, bid) else: print(stockcode,'可用资金',cash) #资金账户变化主推函数 def account_callback(ContextInfo, accountInfo): print('accountInfo') print(accountInfo.m_strStatus) # m_strStatus 为资金账号的属性之一,表示资金账号的状态 #账号委托状态变化主推函数 def order_callback(ContextInfo, orderInfo): print('orderInfo') #账号成交状态变化主推函数 def deal_callback(ContextInfo, dealInfo): print('dealInfo') #账号持仓状态变化主推函数 def position_callback(ContextInfo, positonInfo): print('positonInfo') #************************************************************************************************************** #读取文件 def get_order_symbol(path_order): symbol = [] with open(path_order) as csvfile: reader = csv.DictReader(csvfile) symbol = [row["STOCK"] for row in reader] symbol = capitalize_list(symbol) return symbol def get_dict_order(path_order, item_name): result = {} with open(path_order) as csvfile: reader = csv.DictReader(csvfile) for item in reader: stock_symbol = item["STOCK"] stock_symbol = stock_symbol.upper() #转大写 result[stock_symbol] = float(item[item_name]) return result #获取账户资产总额 def get_accountvalue(accountid,datatype): result=0 acct_info = get_trade_detail_data(accountid,datatype,"ACCOUNT") for obj in acct_info: result=obj.m_dBalance return result #获取当前可用资金 def get_avaliablecash(accountid,datatype): result=0 acct_info = get_trade_detail_data(accountid,datatype,"ACCOUNT") for obj in acct_info: result=obj.m_dAvailable return result #获取当前持仓(手) def get_holdings(accountid,datatype): holdings={} resultlist = get_trade_detail_data(accountid,datatype,"POSITION") for obj in resultlist: holdings[obj.m_strInstrumentID+"."+obj.m_strExchangeID]=obj.m_nVolume/100 return holdings #获取持仓成本 def get_holdingsCost(accountid,datatype): holdings={} resultlist = get_trade_detail_data(accountid,datatype,"POSITION") for obj in resultlist: holdings[obj.m_strInstrumentID+"."+obj.m_strExchangeID]=obj.m_dOpenPrice return holdings #获取可用持仓(手) def get_holdingsAvalable(accountid,datatype): holdings={} resultlist = get_trade_detail_data(accountid,datatype,"POSITION") for obj in resultlist: holdings[obj.m_strInstrumentID+"."+obj.m_strExchangeID]=obj.m_nCanUseVolume/100 return holdings #获取委托号 def get_orderID(accountid,datatype): orderID={} resultlist = get_trade_detail_data(accountid,datatype,"ORDER") for obj in resultlist: orderID[obj.m_strInstrumentID+"."+obj.m_strExchangeID]=obj.m_strOrderSysID return orderID #获取已成交委托号 def get_dealID(accountid,datatype): dealID={} resultlist = get_trade_detail_data(accountid,datatype,"DEAL") for obj in resultlist: dealID[obj.m_strInstrumentID+"."+obj.m_strExchangeID]=obj.m_strOrderSysID return dealID #取消以前买入委托 def cancel_buyorder(stockcode, ContextInfo, accountid): if stockcode in list(ContextInfo.orderID.keys()):#如果有委托 #print("cancel_buyorder") orderId = orders[stockcode] #获取委托号 canCancel = can_cancel_order(orderId, accountid, "stock") #查询委托是否可撤销 if canCancel: cancel(orderId, accountid, "stock", ContextInfo) #取消以前委托 #符号列表小写转大写 def capitalize_list(stringlist): list = [s.upper() for s in stringlist if isinstance(s,str)==True] return list #获取买入清单 def get_buylist(order_smbol, order_bid, numbersOfSortedBid): symbol = [] for s in range(numbersOfSortedBid): if order_bid[order_smbol[s]] > 0: symbol.append(order_smbol[s]) return symbol #去除列表中的重复项 def trim_list(trade_code_list): mylist = [] for s in range(len(trade_code_list)): if trade_code_list[s] not in mylist: mylist.append(trade_code_list[s]) return mylist #计算可用仓位订单份数 def get_positionAvalable_levels(positionAvalable, cost, unitOrderValue): return round(100 * positionAvalable * cost / unitOrderValue, 0) #计算新买入订单份数 def get_positionNew_levels(position, positionAvalable, close, unitOrderValue): return round(100 * (position - positionAvalable) * close / unitOrderValue, 0) #止损条件 def Ready_to_stoploss(close, cost, stoploss, stopLimit): return close/cost - 1 < -stopLimit or close < stoploss #刷新追踪卖出价 def get_trailing_ask(ask, close, ask_step): value = round(close * (1 - ask_step), 2) if ask < value: ask = value return ask #刷新追踪买入价 def get_trailing_bid(bid, close, bid_step): value = round(close * (1 + bid_step), 2) if bid > value: bid = value return bid #计算卖出触发价 def get_delta_sell(ask, ask_delta): value = round(ask * ask_delta, 2) return value #计算买入触发价 def get_delta_bid(bid, bid_delta): value = round(bid * bid_delta, 2) return value #计算卖出数量(手) def get_position_sell(positionAvalable, positionAvalable_levels): position = positionAvalable if positionAvalable_levels > 1: position = int(positionAvalable/positionAvalable_levels) return position