'''backtest start: 2020-03-11 00:00:00 end: 2020-04-09 23:59:00 period: 1d exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}] ''' import pandas as pd import numpy as np import re preBarTime_1=0 ''' shortChart = { "__isStock" : True, "extension" : { "layout" : "group", #single不参于分组,单独显示, 默认为分组 'group' "height" : 300, }, "title" : {"text": 'rb888' + '__15M交易信号图'}, "xAxis" : {"type" : "datetime"}, # 时间序列轴 "yAxis" : [{"labels": { "align": 'right', "x": -3 }, "title": { "text": '盘口' }, "height": "45%", # 相对宽度大小 "resize": { "enabled": True # 是否启用重置宽度 }, "opposite": True, # 是否将轴显示在对面 默认左 "offset": 0, # 坐标轴偏移 正右 负左 "lineWidth": 2 # 线宽 }, {"labels": { "align": 'right', "x": -3 }, "title": { "text": 'RSI' }, "top": '45%', "height": '25%', "opposite": True, "offset": 0, "lineWidth": 2 }, {"labels": { "align": 'right', "x": -3 }, "title": { "text": 'MACD_5' }, "top": '70%', "height": '30%', "opposite": True, "offset": 0, "lineWidth": 2 } ], "tooltip":{ "split": False, # 原生js?? "xDateFormat" : "%Y-%m-%d %H:%M:%S, %A" }, "series" : [{'type': 'candlestick', 'name': 'k线', #'color': 'green', #'lineColor': 'green', # 默认显示color的设置,非null这按照这里的设置显示 #'upColor': 'red', #'upLineColor': 'red', "data" : [], }, { "type" : "line", "name" : "rsi", "data" : [], "yAxis": 1 # 相对位置 } , { "type" : "line", "name" : "diff", "data" : [], "yAxis": 2 # 相对位置 }, { "type" : "line", "name" : "dea", "data" : [], "yAxis": 2 # 相对位置 }, { "type" : "column", "name" : "macd", "data" : [], "yAxis": 2 # 相对位置 } ] } ''' """ shortChart = { "__isStock" : True, "extension" : { "layout" : "single", #single不参于分组,单独显示, 默认为分组 'group' "height" : 300, }, "title" : {"text": 'rb888' + '__15M交易信号图'}, "xAxis" : {"type" : "datetime"}, # 时间序列轴 "yAxis" : {"labels": { "align": 'right', "x": -3 }, "title": { "text": '盘口' }, #"height": "45%", # 相对宽度大小 #"resize": { # "enabled": True # 是否启用重置宽度 "opposite": True, # 是否将轴显示在对面 默认左 "offset": 0, # 坐标轴偏移 正右 负左 "lineWidth": 2 # 线宽 }, "tooltip" : { "split": false, # 原生js?? "xDateFormat" : "%Y-%m-%d %H:%M:%S, %A" }, "series" : {'type': 'candlestick', 'name': 'k线', #'color': 'green', #'lineColor': 'green', # 默认显示color的设置,非null这按照这里的设置显示 #'upColor': 'red', #'upLineColor': 'red', "data" : [], } } """ shortChart = { "__isStock" : True, "extension" : { "layout" : "single", #single不参于分组,单独显示, 默认为分组 'group' #"height" : 500, }, 'legend': { 'enabled': true # 图例 true开启 }, 'title' : { 'text' : '柱形K线' }, "xAxis" : { "type" : "datetime", #'dashStyle': 'dash' # 准心线样式 虚线 }, # 时间序列轴 'yAxis' : [{ 'labels':{ 'align':'right', 'x':-3 }, 'height':"40%", 'lineWidth':2, #'crosshair': true, # 准心线 'resize':{ 'enabled':true } },{ 'labels':{ 'align':'right', 'x':-3 }, 'title':{ 'text' : 'Volume' }, 'top':'40%', 'height':'15%', 'offset':0, #'crosshair': true, 'lineWidth':2 },{"labels": { "align": 'right', "x":-3 }, "title": { "text": 'RSI' }, "top": '55%', "height": '20%', "opposite": True, "offset": 0, #'crosshair': true, "lineWidth": 2, 'plotLines': [{ 'value': 75, # 值大小 'color': 'green', # 颜色 'dashStyle': 'shortdash', # 线条样式 'width': 0.5, #'label': { # 'text': '多头止盈线' #} },{ 'value': 25, 'color': 'red', 'dashStyle': 'shortdash', 'width': 0.5, #'label': { # 'text': '空头止盈线' #} } ] }, {"labels": { "align": 'right', "x":-3 }, "title": { "text": 'MACD' }, "top": '75%', "height": '25%', "opposite": True, "offset": 0, "lineWidth": 2 } ], 'tooltip':{ #'shared': true, # 是否开启提示标签共享,多图下效果基本等同split "xDateFormat" : "%Y-%m-%d %H:%M:%S, %A", 'shared': true, 'crosshairs': true, 'valueDecimals':2, # 保留小数 #'split':true, # 提示框分开 #'distance': 30, #'padding': 5 #'positioner': { # 'x':150, # 'y':150 #}, #'shadow': false, #'borderWidth': 0, #'backgroundColor': 'rgba(255,255,255,0.8)' }, 'series':[{ 'type':'candlestick', 'animationLimit':'Infinity', 'color': 'green', 'lineColor': 'green', # 默认显示color的设置,非null这按照这里的设置显示 'upColor': 'red', 'upLineColor': 'red', 'name':'appl', 'data':[] },{ 'type':'column', 'name':'Volume', 'data':[], 'yAxis':1 },{ "type" : "line", "name" : "rsi", "data" : [], "yAxis": 2 # 相对位置 },{ "type" : "line", "name" : "diff", "data" : [], "yAxis": 3 # 相对位置 },{ "type" : "line", "name" : "dea", "data" : [], "yAxis": 3 # 相对位置 },{ "type" : "column", "name" : "macd", "data" : [], 'maxPointWidth':2, # 量柱最大宽度 "yAxis": 3 # 相对位置 } ] } longChart = { "__isStock" : True, "extension" : { "layout" : "group", #"height" : 300, }, 'rangeSelector':{ 'selected' : 0 }, 'chart': { # 主配置项 #'height': 630, # 高度,平台不支持配置 'type': 'line', 'zoomType': 'x', # 缩放 #'selectionMarkerFill':'rgba(51,92,223,0.25)', # 缩放框背景色 #'panning': true, # 开启平移 #'panKey': 'shift' # 平移 'borderColor': '#EBBA95', # 外框配置项 'borderWidth': 2, ## 'borderRadius': 10, ## }, "rangeSelector" : { "buttons" : [{ "type" : "hour", "count" : 1, "text" : "1h", }, { "type" : 'hour', "count" : 3, "text" : "3h" }, { "type" : "day", "count" : 1, "text" : "1d" }, { "type" : "week", "count" : 1, "text" : "1w" }, { "type" : "year", "count" : 1, "text" : "1Y" }, { "type" : "all", "text" : "All" }], "selected" : 1, "inputEnabled" : True }, 'legend': { 'enabled': true # 图例 true开启 }, 'title' : { 'text' : '15' }, 'subtitle': { 'text': '湘水看盘图表', #'当前价格:'+str(records_5[-1]['Close'] if records_5[-1]['Close'] is not None else **)+' || '+'当前时间:'+str(Time_5 if Time_5 is not None else **) }, "xAxis" : { "type" : "datetime", #'dashStyle': 'dash' # 准心线样式 虚线 }, # 时间序列轴 "xAxis" : {"type" : "datetime"}, "yAxis" : [{ "title": { "text": 'Kline' }, "height": "60%", # 相对宽度大小 "offset": 0, # 坐标轴偏移 正右 负左 "lineWidth": 2 # 线宽 },{ "title": { "text": 'MACD' }, "top": '62%', "height": '38%', "offset": 0, "lineWidth": 2 } ], "series" : [ { "type" : "candlestick", "name" : "k_15", "id" : "k", "data" : [], "yAxis": 0 # 相对位置 },{ "type" : "column", "name" : "macd_15", "data" : [], "yAxis": 1 # 相对位置 } ] } chart0 = { "__isStock" : True, "extension" : { "layout" : "group", #"height" : 300, }, 'title' : { 'text' : '日K线图'}, 'xAxis': { 'type': 'datetime'}, 'series' : [ { 'type': 'candlestick', 'name': 'r', 'id': 'r', 'data': [] }, { 'type': 'column', 'name': 'vol', 'data': [], } ] } chart1 = { "__isStock" : True, "extension" : { "layout" : "group", #"height" : 300, }, 'title' : { 'text' : 'ris'}, 'xAxis': { 'type': 'datetime'}, 'yAxis' : { 'title': {'text': 'rsi'}, 'opposite': false }, 'series' : { 'type': 'line', #'yAxis': 1, 'name': 'rsi', 'data': [] }, } chart2 = { "__isStock" : True, "extension" : { "layout" : "group", #"height" : 300, }, 'title' : { 'text' : 'macd'}, 'xAxis': { 'type': 'datetime'}, 'yAxis' : { 'title': {'text': 'macd'}, 'opposite': false }, 'series' : [ { 'type': 'line', #'yAxis': 1, 'name': 'dif', 'data': [] },{ 'type': 'line', #'yAxis': 1, 'name': 'eda', 'data': [] },{ 'type': 'line', #'yAxis': 1, 'name': 'macd', 'data': [] }, ] } hart1 = { "__isStock" : True, "extension" : { "layout" : "group", #"height" : 300, }, 'title' : { 'text' : 'MACD_5'}, 'xAxis': { 'type': 'datetime'}, 'series' : [ { 'type': 'candlestick', 'name': 'k', 'id': 'r1', 'data': [] }, { 'type': 'column', 'name': 'macd_15', 'data': [], } ] } macd_15 = [] runTime = {} runTime['preBarTime_1'] = [0,0] runTime['arrKIndex'] = [] _5_lengh = 50 _15_lengh = 50 def ticks_(records, k): if len(records) == 0: return [] if isinstance(records[0], int) or isinstance(records[0], float): return records ticks = [None] * len(records) for i in range(len(records)): ticks[i] = records[i][k] return ticks def plot(arr,_5_lengh,_15_lengh,index_2,runTime,chart): for x,symbol in enumerate(arr): #Log(symbol,_D(),) runTime['arrKIndex'] = [index_2[x],index_2[x]+7] # [0,7] [8,15] #Log(symbol) exchange.SetContractType(symbol) #Log(symbol,_D()) records_5 = _C(exchange.GetRecords,PERIOD_M5) # 返回列表型字典 records_15 = _C(exchange.GetRecords,PERIOD_M15) r = records_5 m = records_15 Time_5 = records_5[-1]['Time'] Time_5_list = pd.Series(ticks_(records_5,'Time')) # 小周期开盘时间数组 #Open_5 = records_5['Open'] #High_5 = records_5['High'] #Low_5 = records_5['Low'] Close_5 = pd.Series(ticks_(records_5,'Close')) # 小周期收盘价数组 Time_15 = records_15[-1]['Time'] Time_15_list = pd.Series(ticks_(records_15,'Time')) # 小周期开盘时间数组 #Open_5 = records_5['Open'] #High_5 = records_5['High'] #Low_5 = records_5['Low'] Close_15 = pd.Series(ticks_(records_15,'Close')) # 小周期收盘价数组 #Log(2) ''' nowdea_15 = dea_15[-1] nowdiff_15 = diff_15[-1] nowmacd_15 = macd_15[-1] ''' ''' predea_15 = dea_15[-2] prediff_15 = diff_15[-2] premacd_15 = macd_15[-2] ''' #index_1 += 5 if not r or not m: return #Log(3,len(r)) if len(r) < _5_lengh: # 过滤K线过短情况 return #Log(4) Macd_5 = TA.MACD(r, fastEMA = fastEMA, slowEMA=slowEMA, signalEMA=signalEMA) diff_5 = Macd_5[0] dea_5 = Macd_5[1] macd_5 = pd.Series(Macd_5[2]).fillna(0) macd_5 = macd_5.values*2 # TA的macd算法未乘以2 Macd_15 = TA.MACD(r, fastEMA = fastEMA, slowEMA=slowEMA, signalEMA=signalEMA) diff_15 = Macd_15[0] dea_15 = Macd_15[1] macd_15 = pd.Series(Macd_15[2]).fillna(0) macd_15 = macd_15.values*2 # TA的macd算法未乘以2 RSI = TA.RSI(records_5, period = rsi_period) nowdea_5 = dea_5[-1] nowdiff_5 = diff_5[-1] nowmacd_5 = macd_5[-1] if len(macd_15) > 2: nowmacd_15 = macd_15[-1] nowrsi = RSI[-1] predea_5 = dea_5[-2] prediff_5 = diff_5[-2] premacd_5 = macd_5[-2] if len(macd_15) > 2: premacd_15 = macd_15[-2] prersi = RSI[-2] #Log('K线长度',len(r),'dea_5',len(dea_5),'rsi',len(RSI),preBarTime_1) if len(macd_15)>0: #Log(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(records_5[-1]['Time'])/1000)),_D(),macd_15[-1]) pass #r = records_5 #m = records_15 arr_ = [r,m] #Log(index_2) index_2 = index_2.copy() #index_2 = index_2.tolist() for i in range(len(arr_)): # i 是k线周期循环 #Log(runTime['arrKIndex']) for j in range(len(arr_[i])): # 时间周期循环 #Log(arr_[i][j]["Time"],runTime['preBarTime_1'][i]) if arr_[i][j]["Time"] == runTime['preBarTime_1'][i]: # preBarTime初始为0 if i == 0: #5分钟 #index_2 0 8 chart.add(int(index_2[x]), [arr_[i][j]["Time"], arr_[i][j]["Open"], arr_[i][j]["High"], arr_[i][j]["Low"], arr_[i][j]["Close"]], -1) # 选出不同周期K线的index #Log(1,int(index_2[i])) if i == 0 and len(arr_[i]) > _5_lengh: #Log(2) if j == len(arr_[i]) - 2: #Log(3) chart.add(int(index_2[x]) + 1, [arr_[i][j]["Time"], arr_[i][j]["Volume"]],-1) chart.add(int(index_2[x]) + 2, [arr_[i][j]["Time"], prersi], -1) # 快线 chart.add(int(index_2[x]) + 3, [arr_[i][j]["Time"], prediff_5], -1) # 慢线 chart.add(int(index_2[x]) + 4, [arr_[i][j]["Time"], predea_5], -1) chart.add(int(index_2[x]) + 5, [arr_[i][j]["Time"], premacd_5], -1) elif j == len(arr_[i]) - 1: #Log(4,int(index_2[i])) chart.add(int(index_2[x]) + 1, [arr_[i][j]["Time"], arr_[i][j]["Volume"]],-1) #Log(4.1) chart.add(int(index_2[x]) + 2, [arr_[i][j]["Time"], nowrsi], -1) # 快线 #Log(4.2) chart.add(int(index_2[x]) + 3, [arr_[i][j]["Time"], nowdiff_5], -1) # 慢线 #Log(4.3) chart.add(int(index_2[x]) + 4, [arr_[i][j]["Time"], nowdea_5], -1) #Log(4.4) chart.add(int(index_2[x]) + 5, [arr_[i][j]["Time"], nowmacd_5], -1) #Log(4.5) ''' if i == 1 and len(arr_[i]) > _15_lengh: if j == len(arr_[i]) - 2: chart.add(index_2 + 8, [arr_[i][j]["Time"], premacd_15], -1) # 快线 elif j == len(arr_[i]) - 2: chart.add(index_2 + 8, [arr_[i][j]["Time"], nowmacd_15], -1) # 快线 ''' elif arr_[i][j]["Time"] > runTime['preBarTime_1'][i]: # 初始运行此处 每个5,15分钟运行两次 if i ==1: pass #Log(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(arr_[i][j]["Time"])/1000)),time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(runTime['preBarTime_1'][i])/1000)),'//',i) runTime['preBarTime_1'][i] = arr_[i][j]["Time"] # K线时间赋值给preBarTime Log(runTime['preBarTime_1'][0],runTime['preBarTime_1'][1]) # 0 7 8 15 chart.add(int(runTime['arrKIndex'][x]), [arr_[i][j]["Time"], arr_[i][j]["Open"], arr_[i][j]["High"], arr_[i][j]["Low"], arr_[i][j]["Close"]]) if i ==0 and len(arr_[i]) > _5_lengh: #Log('i=0',int(runTime['arrKIndex'][x])) if j == len(arr_[i]) - 1: chart.add(int(index_2[x]) + 1, [arr_[i][j]["Time"], arr_[i][j]["Volume"]]) chart.add(int(index_2[x]) + 2, [arr_[i][j]["Time"], nowrsi]) chart.add(int(index_2[x]) + 3, [arr_[i][j]["Time"], nowdiff_5]) chart.add(int(index_2[x]) + 4, [arr_[i][j]["Time"], nowdea_5]) chart.add(int(index_2[x]) + 5, [arr_[i][j]["Time"], nowmacd_5]) if i == 1 and len(arr_[i]) > _15_lengh: Log('i=1',int(index_2[x]) + 7) if j == len(arr_[i]) - 1: chart.add(int(index_2[x]) + 7, [arr_[i][j]["Time"], nowmacd_5]) def main(): """ """ global preBarTime_1,macd_15,runTime,_5_lengh,_15_lengh,shortChart,longChart,chart0,chart1,chart2,hart1 if exchange.GetName().find("CTP") == -1: raise Exception("只支持商品期货CTP") SetErrorFilter("login|ready|流控|连接失败|初始|Timeout") mode = exchange.IO("mode", 0) if mode is None: raise Exception("切换模式失败,请更新到最新托管者!") while not exchange.IO("status"): Sleep(3000) LogStatus("正在等待与交易服务器连接," + _D()) positions = _C(exchange.GetPosition) # 获取当前持仓信息字典 if len(positions) > 0: Log("检测到当前持有仓位,系统将开始尝试恢复进度...") Log("持仓信息:", positions) tts = [] # arrChart_1 = [] # 图表数组 arrChart_2 = [] index_ = 0 # index_2 = [] arrKIndex = [] a = [] b = [] c = [] d = [] #while True: #Log(1) symbolFilter = {} # 过滤用数组 arr = Instruments.split(",") # 合约列表 for i in range(len(arr)): # 遍历合约列表 symbol = re.sub(r'/\s+$/g', "", re.sub(r'/^\s+/g', "", arr[i])) # 规整合约字符串 if symbol in symbolFilter.keys(): # 如果 在过滤数组中 存在 名为 symbol的属性,则显示信息 并跳过。 raise Exception(symbol + "已经存在,请检查参数!") symbolFilter[symbol] = True # 给过滤数组 添加 名为 symbol 的 keys,下次 同样的 合约代码 会被过滤 保证每个合约只对Manager类方法传入一次参数 hasPosition = False # 初始化 hasPosition 变量 false 代表没有持仓 for j in range(len(positions)): # 遍历 获取到的持仓信息 if positions[j]["ContractType"] == symbol: # 如果持仓中有合约名等于symbol Log('cc') hasPosition = True # 标记 True 持仓 break # 跳出 #fastPeriod = int(arrFastPeriod[i]) # 规整为数值型 #slowPeriod = int(arrSlowPeriod[i]) Log(123) obj_1 = shortChart # 实例化Manager类 obj_2 = longChart index_2.append(index_) # 0 8 index_ += 8 # 长周期的图表index #tts.append(obj) # tts列表传入 最终根据合约列表 ,生成了若干个品种的 控制对象储存在tts数组 #Log(obj) arrChart_1.append(obj_1) # 在for循环中 依次把图表信息字典传入图表数组 #arrChart_2.append(obj_2) a.append(chart0) b.append(chart1) c.append(chart2) d.append(hart1) Log(len(arrChart_1)) Log(111 if arrChart_1[0]==shortChart else 000) #arrChart_2.append(obj.longChart) # 创建图表对象 #chart = Chart([arrChart_1, arrChart_2]) # __isStock" : True表示是highstock图,False表示是highcharts图 使用多图表对象,转为二维数组 #chart = Chart([arrChart_1,arrChart_2]) chart = Chart([a,b,c,d]) #Log(len(arrChart_1),len(arrChart_2)) index_2 = np.array(index_2) chart.reset() # 清空上次轮询的图表数据 while True: #c = Chart(shortChart) preTicker = None #while True: #Log(1) if exchange.IO('status'): LogStatus(_D(),'已经连接') #t = exchange.GetTicker() plot(arr,_5_lengh,_15_lengh,index_2,runTime,chart) Sleep(1000) ''' if i ==0: if signals['buy_sell_sig'+str(trueSymbol)] ==1: Log(1) #ext.PlotFlag(r[-2]['Time'],'开多','L','circlepin','K') chart.add(index_2 + 6, [arr_[i][j]["Time"], {'X':arr_[i][j]["Time"],'title':'L','text':'开多'}]) signals['buy_sell_sig'+str(trueSymbol)] =0 if signals['buy_sell_sig'+str(trueSymbol)] ==2: Log(2) #ext.PlotFlag(r[-2]['Time'],'开空','S','circlepin','K') chart.add(index_2 + 6, [arr_[i][j]["Time"], {'X':arr_[i][j]["Time"],'title':'S','text':'开空'}]) signals['buy_sell_sig'+str(trueSymbol)] =0 if signals['buy_sell_sig'+str(trueSymbol)] ==3: Log(3) #ext.PlotFlag(r[-2]['Time'],'平多','UL','circlepin','K') chart.add(index_2 + 6, [arr_[i][j]["Time"], {'X':arr_[i][j]["Time"],'title':'UL','text':'平多'}]) signals['buy_sell_sig'+str(trueSymbol)] =0 if signals['buy_sell_sig'+str(trueSymbol)] ==4: Log(4) #ext.PlotFlag(r[-2]['Time'],'平空','US','circlepin','K') chart.add(index_2 + 6, [arr_[i][j]["Time"], {'X':arr_[i][j]["Time"],'title':'US','text':'平空'}]) signals['buy_sell_sig'+str(trueSymbol)] =0 ''' #index_1 += 9 # 短周期的图表index
发明者量化-小小梦 这个图表画的挺好,牛啤!熟悉的挺快的,加油! 貌似策略缺少了个参数: Instruments 这个合约列表字符串缺少了。