主题:1-X技术分析测试程序代码帖 -- 牛义缂
比EXCEL强,又考虑到随时会用到JET,所以。。。
可以这么简单来判断, 假设ma破掉 ema买没破,那么还会有走好。
如果2个都破基本就挂了。
实际短期均线干长期线的时候, ma比ema更早破掉,这样信号失误较多,所以可以拿ema辨识,以免被诱惑。
http://www.accessoft.com/article-show.asp?id=1655
不过小牛还是无法想明白,为什么单测EMA比MA差
MA算法和EMA算法你知道的
MA累加后无法对近期平滑,因此最终影响线的是远期数据
EMA对近期数据权重增加,使得更为平滑,但是也有点慢。
这2个具体类似KDJ与KD的区别。
所以当MA 5日叉10日可能 EMA还没反应, 于是如果作为下跌判断是否逃逸,就可以参考EMA,假设EMA最终5日没破10日,则MA发出信号为假。
如果连EMA都破位虽然不敢说那不是诱空洗盘,但是起码要在恢复上涨不是几日就行,可能需要相对较长时间。 因此有这2个比较后你可以思考自己的进退。
汗哪,现在才发现一直没搞清ACCESS是啥东西,一直把他当成个数据库了,跟JET搞混了。
由于EMA的最优值测试结果比MA(SMA)差很多,小牛开始怀疑EMA均线的优点。于是就试着把MACD作一下改动,把其中的EMA均线全部换成MA均线。
我们把这种新方法叫做MACD',那么它的公式就变成了:
MACD'三个参数:A,B,C
MACD'中的DIF' = 收盘价的MA(A) - 收盘价的MA(B)
MACD'中的DEA' = DIF'的MA(C)
MACD'中的柱线MACD' = (DIF' - DEA') x 2
结果MACD'的最优值测试结果和MACD相比出人意料的好,谁能解释啊?
------------------------
MACD'-DIF'/DEA'交叉方法描述:
1.买入策略:MACD'的DIF'线金叉DEA'线时,第二天开盘买入。
2.卖出策略:MACD'的DIF'线死叉DEA'线时,第二天开盘卖出。
------------------------
注:
1.通达信类软件中,可以通过修改/创建公式来显示MACD'。
2.通达信类软件中,需要缩小K线图至显示全部历史数据,然后再放大到观察点,软件才能正确计算MACD'。
------------------------
表结构
字段名 类型 备注
DATE 日期
OPEN 货币 开盘价
HIGH 货币 最高价
LOW 货币 最低价
CLOSE 货币 收盘价
VOL 长整型 成交量
----------------------------------------
'VBA模块1(要设置的参数都在INITIALIZE()子程序中注释出来了)
Option Compare Database
Option Explicit
'数组RD1()存储交易记录,如果程序提示下标越界,需要增加第二维的下标
Public DP1 As Variant, RD1(2, 499) As Variant, U1 As Long, TIMES As Long, MA1() As Currency, MA2() As Currency, TRATE As Currency, CODE As String
Sub INITIALIZE()
Dim R1 As Variant, M1 As Long, M2 As Long, M3 As Long, B As Long, S As Long, ST As Date, ET As Date, TX As Currency, MX As Currency
R1 = Array("DATE", "CLOSE", "OPEN")
'ST:测试区域的开始日期(注意您的机器上的日期格式)
'注意:开始日期前面要留足计算均线的日期。例如,如果你要用到200日均线,开始日期前面要有至少200条数据。
ST = #12/2/1997#
'ET:测试区域的终止日期(注意您的机器上的日期格式)
ET = #7/2/2010#
'TX:总手续费(只作用于卖价)
TX = 0.008
'CODE:数据表名称
CODE = "999999"
Call READ1(R1)
Debug.Print " MA1", "MA2", "MA3", "FROM", "TO", "手续费", "总收益", "交易次数"
MX = 0
B = 0
S = 0
'M3:DEA'均线值
For M3 = 5 To 300 Step 5
'M1:快MA均线值
For M1 = 5 To 150 Step 5
'M2:慢MA均线值
For M2 = M1 + 15 To 300 Step 5
Call MACL(M1, M2, M3)
Call DEAL(B, S, ST, ET, TX)
'填True时显示所有结果,填False显示特定结果
If False Then
Debug.Print M1, M2, M3, ST, ET, TX * 100 & "%", TRATE, Int(TIMES / 2)
Else
'TRATE>MX:最后一行结果为总收益最大值
'TRATE>5:显示所有总收益大于5的结果
If TRATE > MX Then
Debug.Print M1, M2, M3, ST, ET, TX * 100 & "%", TRATE, Int(TIMES / 2)
MX = TRATE
End If
End If
Next
Next
Next
'填True时显示循环中最后一对双均线的交易记录,填False不显示
If False Then
Debug.Print "日期", "正买负卖", "每次收益"
For B = 0 To TIMES - 1
For S = 0 To 2
Debug.Print RD1(S, B),
Next
Debug.Print
Next
End If
End Sub
Sub READ1(R1 As Variant)
Dim CN1 As ADODB.Connection, RST1 As ADODB.Recordset, SPath As String
SPath = Application.VBE.ActiveVBProject.FileName
Set CN1 = New ADODB.Connection
Set RST1 = New ADODB.Recordset
CN1.CursorLocation = adUseClient
CN1.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & SPath & ";"
RST1.Open "SELECT * FROM " & CODE & " ORDER BY DATE;", CN1, adOpenForwardOnly, adLockReadOnly, adCmdText
RST1.MoveFirst
DP1 = RST1.GetRows(, , R1)
U1 = UBound(DP1, 2)
RST1.Close
CN1.Close
Set RST1 = Nothing
Set CN1 = Nothing
End Sub
Sub MACL(M1 As Long, M2 As Long, M3 As Long)
Dim I As Long, T As Long, TMP1 As Currency
ReDim MA1(U1)
ReDim MA2(U1)
'TEMP MA1()
TMP1 = 0
For I = 0 To M1 - 2
TMP1 = TMP1 + DP1(1, I)
MA1(I) = 0
Next
TMP1 = TMP1 + DP1(1, M1 - 1)
MA1(M1 - 1) = TMP1 / M1
For I = M1 To U1
TMP1 = TMP1 + DP1(1, I) - DP1(1, I - M1)
MA1(I) = TMP1 / M1
Next
'DIFF-MA1()
TMP1 = 0
For I = 0 To M2 - 2
TMP1 = TMP1 + DP1(1, I)
MA2(I) = 0
MA1(I) = MA1(I) - MA2(I)
Next
TMP1 = TMP1 + DP1(1, M2 - 1)
MA2(M2 - 1) = TMP1 / M2
MA1(M2 - 1) = MA1(M2 - 1) - MA2(M2 - 1)
For I = M2 To U1
TMP1 = TMP1 + DP1(1, I) - DP1(1, I - M2)
MA2(I) = TMP1 / M2
MA1(I) = MA1(I) - MA2(I)
Next
'DEA-MA2()
TMP1 = 0
For I = 0 To M3 - 2
TMP1 = TMP1 + MA1(I)
MA2(I) = 0
Next
TMP1 = TMP1 + MA1(M3 - 1)
MA2(M3 - 1) = TMP1 / M3
For I = M3 To U1
TMP1 = TMP1 + MA1(I) - MA1(I - M3)
MA2(I) = TMP1 / M3
Next
End Sub
Sub DEAL(DBUY As Long, DSELL As Long, DT1 As Date, DT2 As Date, TAX As Currency)
Dim I As Long, J As Long, D1 As Long, D2 As Long, DBOK As Boolean, DSOK As Boolean, BGT As Boolean
If DT1 > DT2 Then
MsgBox "日期错误!"
Exit Sub
End If
BGT = False
TIMES = 0
TRATE = 1
D1 = D2N(DT1, "S")
D2 = D2N(DT2, "E")
For I = D1 To D2 - 1
If MA1(I - 1) <= MA2(I - 1) And MA1(I) > MA2(I) Then
If Not BGT Then
RD1(0, TIMES) = DP1(0, I + 1)
RD1(1, TIMES) = DP1(2, I + 1)
TIMES = TIMES + 1
BGT = True
Else
'Stop
End If
Else
If (MA1(I - 1) >= MA2(I - 1) And MA1(I) < MA2(I)) Then
If BGT Then
RD1(0, TIMES) = DP1(0, I + 1)
RD1(1, TIMES) = -DP1(2, I + 1)
RD1(2, TIMES) = DP1(2, I + 1) / RD1(1, TIMES - 1) * (1 - TAX)
TRATE = TRATE * RD1(2, TIMES)
TIMES = TIMES + 1
BGT = False
Else
'Stop
End If
End If
End If
Next
End Sub
Function D2N(DT As Date, DR As String) As Long
Dim J As Long, K As Long, M As Long
J = 0
K = U1
M = Int((K - J) / 2) + J
Do
Select Case DT
Case DP1(0, M)
D2N = M
Exit Function
Case Is < DP1(0, M)
K = M
M = Int((K - J) / 2) + J
Case Else
J = M
M = Int((K - J) / 2) + J
End Select
Loop Until K - J = 1
If DR = "S" Then
If DT > DP1(0, J) Then
D2N = K
Else
D2N = J
End If
Else
If DT < DP1(0, K) Then
D2N = J
Else
D2N = K
End If
End If
End Function
本帖一共被 1 帖 引用 (帖内工具实现)
MACD 我对这东西不感冒.我觉得不好用
你为啥不研究布林带呢 自动交易的话 应该是这种 时时区间预测系统才好.
调试中D1的值为0导致错误,因此改D1 = D2N(DT1, "S")为D1 = D2N(DT1, "S")+1,似乎不 应影响结果。尚祈明示。
如果你在大时间段内测试,你的改动几乎完全不影响结果。
不过我从来没遇到D1=0的情况,你可以把Initialize()中设置的参数发给我,我来跑一下
您的的解释与我的理解没有偏差。
使用600232的xls文件导入mdb,未作修改,在access2003中直接复制代码后调试,尚未加入窗体等等,即出现前述错误,我也很奇怪。但程序就是这样的,呵呵,通过就是成功,现进一步调试中。
松花。
因为我没有用过Access。