手把手教会你构建自己的交易系统 - 6
[互 助] 47万
YearWeek列,主要用于判断当前处于哪一年的第几周。分别使用了year函数、weeknum函数(这个函数在Excel 2007之前不能直接引用,需要加载Analysis Tool Pack后才可使用)、Text函数和Value函数。使用text函数的原因是,如果直接将年与周通过&连接,会出现200212和20022不同长度的数值,所以需要将每年的前6个月(1位数)前面加一个0,从而使得YearWeek列所有数值为6位数。Value函数是将字符串转为数字。 进场列则使用了一个简单的判断,如果5日均线大于30日均线,就显示年与周,否则为0。 在daily表格的工作就比较多了。 首先增加两列:YearWeek, Cross YearWeek列和weekly表格一样,都是得到哪一个年的哪一周。 Cross列,用于判断两列数据K和D的交叉。如果K上穿D,就是1,;如果K下穿D,就是-1;否则为0。我们本可以通过Excel内置函数直接计算K和D的交叉。但是这样一个判断在交易系统中应用比较多,不希望重复使用复杂的嵌套函数,所以这次我们自己用VBA编个函数来判断交叉。代码如下: Function CrossUp(Line1 As Range, Line2 As Range) As Integer '该函数引用不同行的数据进行比较,一旦采用此函数,请不要执行过滤操作 'Line1和Line2所在行为一个指标序列 '判断上穿、下穿的根据就是在穿插点的前后数值的比较 '如果当前Line1数值大于Line2数值而且在前一时点Line1数值小于或者等于Line2数值,就被认为是上穿,返回1; '如果当前Line1数值小于Line2数值而且在前一时点Line1数值大于或者等于Line2数值,就被认为是下穿,返回-1; If ((Line1.Value > Line2.Value) And (Line1.Offset(-1, 0).Value <= Line2.Offset(-1, 0).Value)) Then CrossUp = 1 ElseIf ((Line1.Value < Line2.Value) And (Line1.Offset(-1, 0).Value >= Line2.Offset(-1, 0).Value)) Then CrossUp = -1 Else CrossUp = 0 End If End Function 然后在单元格J2输入=crossup(G2,H2),并填满剩余列中空白单元格。这时KD的交叉已经一目了然。 接下来,我们增加进场列,表示在weekly表格发出信号我们可以进场。我们要使用查找函数vlookup。我们在K2输入=VLOOKUP (I2,weekly!$J$2:$J$485,1)。请注意,这个函数里的参数使用了绝对引用。但是把这个函数填满该列后发现这个函数的返回值出错。为什么?我们需要深入了解函数的机制。VlOOKUP函数的第一个参数,是查找值I2。第二个参数是查找范围或查找数组weekly!$J$2:$J$485,错误原因在于这个查找范围一般在查找前需要排序,而我们在weekly!$J$2:$J$485这列中混有不少零值并没有排序。所以在一般的三个参数后需要加一个参数,我们在K2中输入=VLOOKUP(I2,weekly!$J$2:$J$485,1, FALSE)。然后把该函数填满全列。结果显示正确。该列表示,如果在weekly表中本周可以入场就显示该周的YearWeek。大家可以看到这个函数基本显示正确,但为了在该列不给出进场信号的行中不要显示错误符号,我们结合使用了IsError函数。大家可以自己深入了解这个函数。 再增加交易信号列,在单元格L2输入=IF(J2=1, IF(K2<>0, 1, 0), IF(J2=-1, -1, 0))。这是一个过渡的列。本想一步执行,但考虑到函数的难度,所以增加了这么一列。这个函数是逻辑判断函数。简单地说,就是如果K上穿D(J2=1),同时是可以入场周(K2<>0),就入场。如果K下穿D(J2=-1),就出场。这时候我们看到买卖信号并不是成对的。因为买的操作必须在周线5周均线大于30周均线的情况下才能执行,而卖的操作却可以任意时段执行。所以这一列的数据需要清理。在这一列中,如果单元值为1,表示买进;单元值为-1,表示卖出;单元值为0,表示不操作。 考虑到买卖信号的发出在交易信号列中和实际的买卖操作有一定的规律,所以下面我们再写一段程序简化操作。这段程序对不懂vba的新手来说比较复杂。对于不懂vba的新手,我比较建议你们通过函数解决这个问题。建议大家讨论讨论用函数如何解决这个问题。 ‘调用程序FillDirection,过滤并保留合格交易信号。 Sub BSFilter() Call FillDirection(Range("L2:L2276"), Range("M2:M2276")) End Sub ‘程序模块FillDirection可调用; ‘用于保留合格的买入信号1,以及合格的卖出信号-1 ‘买入卖出信号从Signal读入,合格的信号写入Destination Public Sub FillDirection(Signal As Range, Destination As Range) ' '该模块通过循环选择唯一卖出信号-1; '卖出信号的选择:在买入信号1和下一个买入信号1中,行号最小的卖出信号-1就是我们要找的卖出信号; '该模块运行后,将正确的买入和卖出信号填入到目标区域; 'Signal的最大行号 Dim iSignalRows As Integer 'Signal所在列 Dim iSignalCol As Integer iSignalRows = Signal.Rows.Count iSignalCol = Signal.Column 'Destination所在列 Dim iDestinationCol As Integer iDetinationCol = Destination.Column Dim iDestinationRow As Integer '找到第一个1的行号 'iStart = WorksheetFunction.Match(1, Signal, 0) 'Cells(iStart + 1, iDetinationCol).Value = 1 Dim iStart As Integer Dim iStartTemp As Integer iStart = 0 iStartTemp = 0 Do While Not (WorksheetFunction.IsNA(WorksheetFunction.Match(1, Range(Cells(iStartTemp + 1, iSignalCol), Cells(iSignalRows, iSignalCol)), 0))) iStart = WorksheetFunction.Match(1, Range(Cells(iStartTemp + 1, iSignalCol), Cells(iSignalRows, iSignalCol)), 0) iStartTemp = iStart + iStartTemp Cells(iStartTemp, iDetinationCol).Value = 1 If Not (WorksheetFunction.IsNA(WorksheetFunction.Match(-1, Range(Cells(iStartTemp + 1, iSignalCol), Cells(iSignalRows, iSignalCol)), 0))) Then iStart = WorksheetFunction.Match(-1, Range(Cells(iStartTemp + 1, iSignalCol), Cells(iSignalRows, iSignalCol)), 0) iStartTemp = iStart + iStartTemp Cells(iStartTemp, iDetinationCol).Value = -1 Else Exit Sub End If On Error GoTo Final Loop Final: End Sub 选中Daily表格,然后执行程序BSFilter。这时我们看到M列也就是方向列,有很多1和-1。这些都是买卖进出场信号。我们可以通过菜单过滤操作,只显示交易信号为1和-1的记录,然后把这些记录复制到新建的表格里。再根据这个表格将买卖记录通过函数并排显示在同一行(表示1笔交易),从而方便计算交易系统的结果。这样的操作对于不懂编程的人很方便,但对于经常要重复同样工作的人来说,重复这样的操作出错的概率较大。所以我们用程序来完成这个工作。在编程之前,我们增加三个表格:Analysis、Trades和Result。 下面是第一个程序MakeTrades。 Option Explicit Sub MakeTrades() Application.ScreenUpdating = False Dim cell As Range Dim rngTemp As Range '在交易方向列筛选出所有不为零,也就是把所有显示交易方向的行列出 Worksheets("Daily").Range("A1:M2276").AutoFilter Field:=13, Criteria1:="<>" Set rngTemp = Range("A1").CurrentRegion.SpecialCells(xlCellTypeVisible) Selection.AutoFilter rngTemp.Copy '将所有的显示行复制到Analysis表格中,去掉多余的列数,仅保留交易时间,当日收盘价和交易方向 Worksheets("Analysis").Range("A1").PasteSpecial (xlPasteAll) Worksheets("Analysis").Columns("F:L").Delete Worksheets("Analysis").Columns("B:D").Delete Worksheets("Analysis").Active Application.ScreenUpdating = True End Sub 接下去,我们需要将买卖两行数据合并为一笔交易显示在Trades表格中,作为评测交易系统的原数据。本想把程序ListTrades显示出来。但是考虑到xlsm文件包括所有的源程序,所以,我就不把源程序列在帖子里列出来了。大家慢慢看,自己消化。这部分的内容对于没有VBA和Excel函数基础的人有些困难,但是下点功夫把这两点学会,对于交易系统的构建,是有着极大的帮助的。 网上有朋友(再看看)在《手把手教会你构建自己的交易系统 – 5》中给出交易系统的计算结果,和我的结果有一些偏差。他显示的结果是交易103次,我显示的少一次。盈利也多0.5元。不知道是不是源数据的问题。 我计算出来的结果,可以简单理解为:如果在2002年4月29日以3.36元入场,2011年3月11日,以8.55出场。不考虑除权,资本增值10.32元。如果考虑到除权,增值部分至少翻倍。另外如果对于上证指数周K线5周均线低于30周均线再构建一个交易系统,会继续加大投资利润。所以这样一个最简单最初级的系统就足以保证初级投资者的利润。对于高手来说,加上合理的止损和仓位管理,利润应该可以在此基础上增加50%。 为了对这个系统做一个简单的评估,我们在Trades表格增加利润亏损列和持有时间(工作日)列。 在F2输入:=E2-C2 在G2输入:=NETWORKDAYS(B2,D2) 并把这个公式复制到下面的单元格。 这样,我们就可以简单地计算这个交易系统的数据了。 在交易数据的右方,我添加了一些项目,大家可以看看,这就是这个交易系统的简单评测。 附件下载地址:http://cid-b1eb40781af7ab97.offi ... 0-%20Mar%202011.rar 因时间仓促,错误在所难免。请大家指正。 |
楼主 | 19楼 |
2楼 | 20楼 |
3楼 | 21楼 |
4楼 | 22楼 |
5楼 | 23楼 |
6楼 | 24楼 |
7楼 | 25楼 |
8楼 | 26楼 |
9楼 | 27楼 |
10楼 | 28楼 |
11楼 | 29楼 |
12楼 | 30楼 |
13楼 | |
14楼 | |
15楼 | |
16楼 | |
17楼 | |
18楼 |