MT4_应用于外汇交易的量化模型
- 你好!欢迎浏览本文章
- 模型设计的数据来源
- 历史数据的提取与处理
- 历史数据的选取与提取
- 历史数据的处理
- 寻找符合涨跌要求的历史数据段
- 对已选取时间段的值进行技术分析
- 对每个时间段的值及技术指标值进行绘图
- 调用所有函数并运行
- 数据指标的分析
- 量化模型的编写
你好!欢迎浏览本文章
我是一个交易爱好者,利用工作闲暇时间设计了本交易模型。该模型应用于外汇交易中的欧元与美元对,大致思路为通过对历史近一年的交易数据进行技术分析,找到该时间段内符合涨跌幅度的时间段并计算其对应的交易指标值,后通过对所有时间段下的交易指标值进行分析,综合得出一套交易模型。想法较为朴素简单,欢迎各位指点与交流。
模型设计的数据来源
历史数据的提取与处理
历史数据的选取与提取
关于选取哪个交易时间段,根据我的交易习惯及经验,同时又综合了对网上各种交易经验的总结,最终我选择了5Min的交易时间段。我平常交易的软件为MT4,该软件中存储有每个交易对每个时间段的历史数据,具体提取方式如下:
“工具”——“历史数据中心”——“导出”。
这里有一个小技巧,如果觉得历史数据太少可以往前拖动折线图的界面,直到拖到你想要的数据或者拖不动为止,”历史数据中心“会根据图形的覆盖范围储存相应时间的数据。亦可以在“工具”—“选项”—“图标”中将最多柱数调到最大。如果没有MT4软件的话,也可以直接从网上搜,附上一个网址“https://www.investing.com/currencies/eur-usd-historical-data”。
历史数据的处理
从MT4或者网上下载来的数据需要在表格简单处理一下,最终形式如下:
需要注意的是,“Date”和“DateTime”两列的格式要与图片保持一致,“DateTime”的存在是为了后期给图片与数据存储的表格命名,其格式可参考公式“TEXT(A2,“yyyy-m-d”)&“-”&TEXT(C3,“h-mm”)”。
寻找符合涨跌要求的历史数据段
首先,应确定选取多大的涨跌幅度作为时间段的待选取条件,我选取的涨跌值为0.00350,时间间隔为3。由于外汇交易为双向交易,因此我们需要将做多方向的数据与做空方向的数据分开保存。以下函数的作用为将已有的历史数据进行分类再汇总,后利用遍历循环在历史数据中分别找出做多与做空方向中符合时间间隔为3、涨跌值大于0.00350的时间段。
import pandas as pddef data_process(path, num):# 引入数据列表csvdata = pd.read_csv(path)# 对数据进行简单分类汇总date = data['Date']time = data['Time']open = data['Open']high = data['High']low = data['Low']close = data['Close']volumes = data['Volumes']datetime = data['DateTime']# 遍历数据库,找到符合要求的数据集long_data = []short_data = []totalnum = 0for i in range(0, num, 1):if close[i + 3] - close[i] > 0.00350:totalnum += 1long_data.append({'Date': date[i - 56:i + 5], 'Time': time[i - 56:i + 5], 'Open': open[i - 56:i + 5],'High': high[i - 56:i + 5], 'Low': low[i - 56:i + 5], 'Close': close[i - 56:i + 5],'Volumes': volumes[i - 56:i + 5], 'DateTime': datetime[i - 56:i + 5]})if close[i + 3] - close[i] < -0.00350:totalnum += 1short_data.append({'Date': date[i - 56:i + 5], 'Time': time[i - 56:i + 5], 'Open': open[i - 56:i + 5],'High': high[i - 56:i + 5], 'Low': low[i - 56:i + 5], 'Close': close[i - 56:i + 5],'Volumes': volumes[i - 56:i + 5], 'DateTime': datetime[i - 56:i + 5]})else:continuepd.set_option('display.max_columns', None)pd.set_option('display.max_rows', None)return long_data, short_data
对已选取时间段的值进行技术分析
根据日常交易中常用的技术指标并结合MQL语言(MT4编程语言)中自带的技术指标库,我一共选取了11种技术指标用于分析整理,分别是:RSI、EMA、MACD、布林线、SAR、OBV、ATR、CCI、ADX、STOCH、MFI。本函数利用了Python自带的talib库,利用历史数据中的数据值分别将这些指标进行计算并保存,上手比较简单,理解起来也比较容易。
import talibdef indicators(path, num):indicator = []for i in range(0, num, 1):rsi = talib.RSI(path[i]['Close'])ema = talib.EMA(path[i]['Close'])macd = talib.MACD(path[i]['Close'])bbands = talib.BBANDS(path[i]['Close'])sar = talib.SAR(path[i]['High'], path[i]['Low'])obv = talib.OBV(path[i]['Close'], path[i]['Volumes'])atr = talib.ATR(path[i]['High'], path[i]['Low'], path[i]['Close'])cci = talib.CCI(path[i]['High'], path[i]['Low'], path[i]['Close'])adx = talib.ADX(path[i]['High'], path[i]['Low'], path[i]['Close'])stoch = talib.STOCH(path[i]['High'], path[i]['Low'], path[i]['Close'])mfi = talib.MFI(path[i]['High'], path[i]['Low'], path[i]['Close'], path[i]['Volumes'])indicator.append({'DateTime': path[i]['DateTime'], 'Date': path[i]['Date'], 'Time': path[i]['Time'],'Open': path[i]['Open'], 'High': path[i]['High'], 'Low': path[i]['Low'],'Close': path[i]['Close'], 'Volume': path[i]['Volumes'], 'EMA': ema, 'UpperBand': bbands[0],'MiddleBand': bbands[1], 'LowBand': bbands[2], 'OBV': obv, 'ATR': atr, 'MACD': macd[0],'MacdSignal': macd[1], 'MacdHist': macd[2], 'RSI': rsi, 'SAR': sar, 'StochSlowK': stoch[0],'StochSlowD': stoch[1], 'CCI': cci, 'ADX': adx, 'MFI': mfi})return indicator
对每个时间段的值及技术指标值进行绘图
在绘图这一模块,我选用了Python中的mplfinance库,该Python库专门用于绘制交易图。因为绘图的目的为直观上大致了解时间段内价格及技术指标的走向,因此本函数并没有对图像风格做过多的自定义编写。本函数的目的是将上文收集到符合条件的历史数据段内的价格走势及其相对应的技术指标走势进行绘图,后将图片保存至本地文件夹内。具体代码如下:
import mplfinance as mpf
import pandas as pddef make_graph(data, path):# 引入indicator并作简单数据处理indicator_process = pd.DataFrame(data)indicator_process['Time'] = pd.to_datetime(indicator_process['Time'])indicator_process.set_index('Time', inplace=True)# 设置图像的整体部署kwargs = dict(type='candle', volume=True)add_plot = [mpf.make_addplot(indicator_process['EMA'], panel=2, ylabel='EMA'),mpf.make_addplot(indicator_process['UpperBand']),mpf.make_addplot(indicator_process['MiddleBand']),mpf.make_addplot(indicator_process['LowBand']),mpf.make_addplot(indicator_process['OBV'], panel=3, ylabel='OBV'),mpf.make_addplot(indicator_process['ATR'], panel=4, ylabel='ATR'),mpf.make_addplot(indicator_process['MacdHist'], type='bar', panel=5, ylabel='MACD', color='darkslateblue'),mpf.make_addplot(indicator_process['MACD'], panel=5, color='orangered'),mpf.make_addplot(indicator_process['MacdSignal'], panel=5, color='limegreen'),mpf.make_addplot(indicator_process['RSI'], panel=6, ylabel='RSI'),mpf.make_addplot(indicator_process['SAR'], panel=7, ylabel='SAR'),mpf.make_addplot(indicator_process['StochSlowK'], panel=8, ylabel='StochSlowK'),mpf.make_addplot(indicator_process['StochSlowD'], panel=8),mpf.make_addplot(indicator_process['CCI'], panel=9, ylabel='CCI'),mpf.make_addplot(indicator_process['ADX'], panel=10, ylabel='ADX'),mpf.make_addplot(indicator_process['MFI'], panel=11, ylabel='MFI')]# 画出图像mpf.plot(indicator_process, **kwargs, addplot=add_plot, figratio=(16, 9), figscale=2.5,update_width_config=dict(line_width=0.8), savefig=path)return indicator_process
调用所有函数并运行
上文中,一共出现了三个函数分别为数据处理函数、技术指标计算函数以及绘图函数,现在将这三个函数调用并运行。在运行后,所有符合条件的时间段内的数据及其所对应的交易图像都将被保存至本地。具体调用代码如下:
import pandas as pd
from dataprocess import data_process
from indicator import indicators
from Graph import make_graphcolumn_num = len(pd.read_csv('EURUSD5min.csv'))-3
long_data, short_data = data_process('EURUSD5min.csv', column_num)long_indicator = indicators(long_data, len(long_data))
short_indicator = indicators(short_data, len(short_data))# 将所有数据绘图
for data_indicator in long_indicator:graph_indicator = pd.DataFrame(data_indicator)graph_indicator.set_index('Date', inplace=True)make_graph(data_indicator, ('Graph/long/{}'.format(graph_indicator['DateTime'][59])))for data_indicator in short_indicator:graph_indicator = pd.DataFrame(data_indicator)graph_indicator.set_index('Date', inplace=True)make_graph(data_indicator, ('Graph/short/{}'.format(graph_indicator['DateTime'][59])))# 将所有数据保存为csv格式
for csv_indicator in long_indicator:csv_indicator = pd.DataFrame(csv_indicator)csv_indicator.set_index('Date', inplace=True)csv_indicator.to_csv('csv/long/{}.csv'.format(csv_indicator['DateTime'][59]))for csv_indicator in short_indicator:csv_indicator = pd.DataFrame(csv_indicator)csv_indicator.set_index('Date', inplace=True)csv_indicator.to_csv('csv/short/{}.csv'.format(csv_indicator['DateTime'][59]))
至此,所有的历史数据的处理工作已经完成。本次数据选取的时间间隔为2021年12月6日14:45至2022年11月25日22:50(UTC/GMT +1小时 东一区)。其中符合做多条件时间段的数量为114个,符合做空条件时间段的数量为93个。附上一张数据图及其对应的交易图:
数据指标的分析
对于这一十个指标的分析,我的想法是分成做多与做空两大类并将每种指标当作小类来对待。对每个大类下的每个小类所对应的数百个数据组进行统计分析以找出其中的共性。但遗憾的是,我尝试了如回归、因子分析等一些统计方法都无法达到我预想的分析目标。最终,我选择了最传统的统计分析方法,人工分析并进行数据回测检验。
若各位对如何将这些数据组进行分析有更好的想法,欢迎交流与指点!
量化模型的编写
本次代码的编写我将在交易软件MT4中直接编写,所使用的语言为MQL(MT4制定的编写语言,类似C++)。根据我自己对数据的理解与分析,本次选取EMA、ATR、RSI三种指标进行量化的设计。
首先分别编写EMA、ATR、RSI以及买入的函数。指标函数逻辑分别为:当第2、3、4根K线所对应的EMA之和(第0根对应的是当下k线,数字向前K线向后以此类推)大于第5、6、7根K线所对应的EMA之和时判定为真;当第1、2、3根K线所对应的ATR之和与第4、5、6根K线所对应的ATR之和的比大于1.15时判定为真;当第1、2根K线所对应的RSI之和小于第3、4根所对应的RSI之和时判定为真。
量化的执行逻辑为当以上三个指标函数都判定为真时买入2手,止损价格为买入价减200点,止盈价格为买入价加200点,时间周期为5分钟。代码如下:
//+------------------------------------------------------------------+
//| Tang_Discover.mq4 |
//| Copyright 2022, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property strictdouble mylot;
string currency_pair;
bool ema_longjudge=false;
bool atr_longjudge=false;
bool rsi_longjudge=false;void OnTick(){
//---currency_pair=Symbol();ema_long();atr_long();rsi_long();if(ema_longjudge==true&&atr_longjudge==true&&rsi_longjudge==true){mylot=0.5;buy();}}void buy(){double stoploss=MarketInfo(currency_pair,MODE_ASK)-200*Point;double takeprofit=MarketInfo(currency_pair,MODE_ASK)+200*Point;int ticket=OrderSend(currency_pair,OP_BUY,mylot,MarketInfo(currency_pair,MODE_ASK),5,stoploss,takeprofit);if(ticket<0){Print("OrderSend failed with error",GetLastError());}elsePrint("OrderSend placed successfully");}void ema_long(){double ema_near=iMA(currency_pair,5,30,0,1,PRICE_CLOSE,2)+iMA(currency_pair,5,30,0,1,PRICE_CLOSE,3)+iMA(currency_pair,5,30,0,1,PRICE_CLOSE,4);double ema_far=iMA(currency_pair,5,30,0,1,PRICE_CLOSE,5)+iMA(currency_pair,5,30,0,1,PRICE_CLOSE,6)+iMA(currency_pair,5,30,0,1,PRICE_CLOSE,7);if(ema_near>ema_far){ema_longjudge=true;}else{ema_longjudge=false;}}void atr_long(){double atr_near=iATR(currency_pair,5,14,1)+iATR(currency_pair,5,14,2)+iATR(currency_pair,5,14,3);double atr_far=iATR(currency_pair,5,14,4)+iATR(currency_pair,5,14,5)+iATR(currency_pair,5,14,6);if((atr_near/atr_far)>1.15){atr_longjudge=true;}else{atr_longjudge=false;}}void rsi_long(){double rsi_near=iRSI(currency_pair,5,14,PRICE_CLOSE,1)+iRSI(currency_pair,5,14,PRICE_CLOSE,2);double rsi_far=iRSI(currency_pair,5,14,PRICE_CLOSE,3)+iRSI(currency_pair,5,14,PRICE_CLOSE,4);if(rsi_near<rsi_far){rsi_longjudge=true;}else{rsi_longjudge=false;}}
对于这个量化模型,我进行了数据回测,时间为2022年1月1日至2022年11月29日,回测数据如下:
结束!