5
以 Excel VBA 以以以以以以以以 以以以以以以以以以以以以以 [以以 4.2.1]以 以以以以以 ,一: 1. 以以以以以以以以以以以以以以以以以 2. 以以以以以以以以 、。,一,,,。 3. 以 以以以以 。, 10(N)0.25 以 0.75 以 以 ,。 4. 以 以以以以以以 、。, 0.3 以 以 50%以 以 0.2 以 以 100%以 5. 以以以以以以 6. 以 以以以以以以以以以以 ,、。。, — 以以以以以以以以以以以 0.25 以以以 5 以以以 以以以以 10 以以 以以以以以 — 以以以以以以以以以以以 0.75 以 以以以以以以以 」「 10% 以以以以以 」「 20% 以以以以 」。 以以 Excel 以 以以以 ,, VBA 以以以以以以以以以以以以 以 以以以以以以以以 ,,一, (以 以 ) 以以以以以以以以以以以以以以以 ,,,。一, 「」 Excel VBA 以以以以以以以以 以以以以以以以以以以以以以以以以以 以以以以以以以以 以以以以以以以 以以以以 ,,, VBA 以以 以以以以以以以 ? 以以以以以 以以以 、。 一, (以以以以以以以以以以以以 以以以以以以以 「」 ) VBA 以以以以以以以以以 以以以以以以以以以以以以以以以以以以 Excel 以以以以以以以以以以以以 Excel 以以以[以以 4.2.2 VBA 以 以 ] (以 Ch4_2_VBA_v1.xlsm 以 ) 以以以以以 一, VBA 以以以以以以以 Excel 以以以以以 D 以以 H 以 以 以以以以以以以以以以 ,, 「」 以(G7) ,。 以 以以以以以以以以以 以以以以以以以 「」 (以 以 以 、、) 以以以以 ,,一,。 以以以以以以以以以以以以以以以 4.2.6 以 以 4.2.3 以 以 (以 CommandButton1 以 Click 以 以以以)以以 4.2.4 以以

以Excel VBA進行回溯測試分析

Embed Size (px)

Citation preview

Page 1: 以Excel VBA進行回溯測試分析

以 Excel VBA 進行回溯測試分析

試算表中建立回溯測試的缺憾

以[範例 4.2.1]為基礎,可進一步進行以下分析:

1. 與同期間之股價指數或類股指數相比較。2. 進行更廣泛期間、更廣泛股票之分析。可能的話,以同一規則測試不同股票,以其報酬率與指數比較,進行統計檢定,以確認選股指標之有效性。

3. 調整指標參數。例如,上例心理線指標中的 10(N)、0.25與 0.75等,均為可調變參數。4. 設定分批買進、分批賣出策略。例如,當心理線計算值低於 0.3時,以 50%資金買進股票,低於

0.2時,始投入 100%資金買進股票等。5. 考慮交易成本。6. 考慮其他指標,例如停損點、獲利滿足點等。這些買賣規則可以邏輯運算組合。例如,買進規則為—「當心理線指標小於或等於 0.25時」且「5日均線往上突破 10日均線」時買進;賣出規則為—「當心理線指標大於或等於 0.75時」或「投資損失達 10%」或「獲利達 20%」時賣出。

欲在 Excel中以格位計算達成以上功能並不容易,因此在以下範例中,將改以VBA編碼設計的表單系統完成之。在完成回溯測試,找出有效的操作規則後,投資人下一步往往希望,以該買賣指標組合(此為投

資策略之一部分),過濾目前可投資的標的物,是否已經觸及買賣點,以在市場中進行操作。此即下一子節,所擬建立之「即時操盤環境」的系統目標。

以 Excel VBA 進行回溯測試分析 既然在試算表格位環境中進行回溯測試,會面臨諸多問題,根本解決之道,即改用「VBA編碼」

來做,但應該如何作呢?

以前一節的範例為基礎,接下來將逐步強化、複雜化該範例。(此即系統開發策略中所謂的「漸進開發策略」)

以 VBA 建立心理線分析模型 以下我們分成幾個階段逐步讓原來建構在 Excel試算環境中的系統逐步脫離 Excel的環境。

[範例 4.2.2:以 VBA 程式碼進行格位計算,並將計算結果傳回格位中]

(參考「Ch4_2_VBA_v1.xlsm」檔案)

在本節第一個範例中,我們透過VBA程式碼計算原本 Excel格位版本中D欄到H欄的計算,將計算結果送回格位中,並將「投資報酬率」計算結果(G7),在表單介面輸出。此外,為了讓「心理線指標回溯測試模型」更加具備彈性,我們把指標參數(心理線計算期間、心

理線判斷下限、心理線判斷上限與分析期間等四個參數),拉到表單輸出入介面中,如此一來,就無須在程式中調整參數。

Page 2: 以Excel VBA進行回溯測試分析

設計妥的心理線分析模型介面如圖 4.2.6所示,使用到的控制項與屬性設定如表 4.2.3所示。主要程式碼(由 CommandButton1之 Click事件趨動)如表 4.2.4所示。

圖 4.2.6範例系統畫面

表 4.2.3 範例中的屬性修改物件(控制項)名稱 修改的屬性名稱 修改前的屬性值 修改後的屬性值Label1 Caption Label1 指標計算天數Label2 Caption Label2 買進下限值Label3 Caption Label3 賣出上限值Label4 Caption Label4 測試筆數Label5 Caption Label4 測試期間報酬率TextBox1 Text Text1 10

TextBox2 Text Text2 0.25

TextBox3 Text Text3 0.75

TextBox4 Text Text4 326

TextBox5 Text Text5 (空值)

Command1 Caption Command1 執行Command2 Caption Command2 離開Frame1 Caption Frame1 心理線測試參數設定Frame2 Caption Frame2 測試績效UserForm1 Caption UserForm1 心理線回測系統

表 4.2.4範例系統程式碼行號 程式碼

1

2

3

4

Private Sub CommandButton1_Click()

''宣告變數型態Dim TimePeriod, TimeSpan As Integer

Dim LowBound, UpBound As Single

Page 3: 以Excel VBA進行回溯測試分析

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

Dim i, j As Integer

'透過介面取得參數TimePeriod = Val(TextBox1.Text) '取得心理線計算期間LowBound = Val(TextBox2.Text) '取得心理線判斷下限UpBound = Val(TextBox3.Text) '取得心理線判斷上限TimeSpan = Val(TextBox4.Text) '取得分析期間'清除輸出格位值For i = 4 To 8

For j = 2 To 326

Cells(j, i) = ""

Next j

Next i

'設定模式初始值Cells(TimePeriod, 6) = 2 '一開始無買賣行動Cells(TimePeriod, 7) = 0 '一開始無股票部位Cells(TimePeriod, 8) = 1 '一開始現金部位'計算「D」欄For i = 2 To TimeSpan

If Cells(i, 3) > 0 Then

Cells(i, 4) = 1

Else

Cells(i, 4) = 0

End If

Next i

'計算「E」~「H」欄Dim UpSum As Single

For i = TimePeriod + 1 To TimeSpan

'計算「E」欄 UpSum = 0

For j = 1 To TimePeriod

UpSum = UpSum + Cells(i - j + 1, 4)

Next j

Cells(i, 5) = UpSum / TimePeriod

'計算「F」欄 If Cells(i, 5) <= LowBound Then

Cells(i, 6) = 1

ElseIf Cells(i, 5) >= UpBound Then

Cells(i, 6) = 3

Else

Cells(i, 6) = 2

End If

Page 4: 以Excel VBA進行回溯測試分析

46

47

48

49

50

51

52

53

54

55

56

57

58

60

61

62

63

64

65

66

'計算「G」欄 If Cells(i - 1, 6) = 1 Then

Cells(i, 7) = Cells(i - 1, 8) / Cells(i, 2) + Cells(i - 1, 7)

ElseIf Cells(i - 1, 6) = 2 Then

Cells(i, 7) = Cells(i - 1, 7)

Else

Cells(i, 7) = 0

End If

'計算「H」欄 If Cells(i - 1, 6) = 1 Then

Cells(i, 8) = 0

ElseIf Cells(i - 1, 6) = 2 Then

Cells(i, 8) = Cells(i - 1, 8)

Else

Cells(i, 8) = Cells(i - 1, 7) * Cells(i, 2) + Cells(i - 1, 8)

End If

Next i

'將「投資報酬率」計算結果輸出TextBox5.Text = Str(Format((Cells(TimeSpan, 7) * Cells(TimeSpan, 2) + Cells(TimeSpan,

8)) - 1, "0.0000"))

End Sub

表 4.2.4程式碼說明如下:行(1)與行(66)間的程式碼為,當 CommandButton1被滑鼠左鍵 Click驅動時執行的程序。行(3)宣告 TimePeriod與 TimeSpan兩變數,分別用以儲存心理線參數計算期間與回溯測試資料

筆數。行(4)宣告 LowBound與UpBound兩變數,分別用以儲存判斷心理線指標為買進或賣出的判斷值。行(5)宣告 i與 j兩變數,分別為用以控制外層迴圈與內層迴圈變化的指標變數。行(7)至行(10)間的程式碼分別用以從 TextBox1, TextBox2, TextBox3與 TextBox4文字框中取得使

用者透過使用介面設定的「心理線參數計算期間」、「判斷心理線指標為買進的判斷值」、「判斷心理線指標為賣出的判斷值」與「回溯測試資料筆數」,並存入相應的變數中。由於取得的值為字串資料型態因此必需透過Val()函數將之轉為數值資料型態。行(12)至行(16)間的程式碼用以將 D欄(第 4欄)至 H欄(第 8欄),以及第 2列到第 326列(資料的

總列數)中的格位清空。行(18)至行(20)間的程式碼分別用以設定回溯測試的啟始條件,並將啟始條件值存入「試算表」相

應格位中。行(22)至行(28)間的程式碼用以計算「D」(第四)欄資料,該欄資料係依據前一欄(「C」(第三)欄)資

料判斷若大於 0則第四欄填「1」,否則填「0」。由於每一列資料都要如此處理,因此將此判斷結構置於一迴圈中,計算由第 2列至第 TimeSpan列的資料。行(30)宣告UpSum變數,用以儲存過去一段時間(TimePeriod變數決定時間長度)上漲天數總合。行(31)至行(63)間的程式碼用以計算從「E」(第五)~「H」(第八)欄的資料,由於每一列都要計算,

Page 5: 以Excel VBA進行回溯測試分析

因此將其置於迴圈中,由於第一筆買賣判斷至少要比 TimePeriod長且第一列為標題列,因此迴圈由TimePeriod + 1開始,至 TimeSpan結束。行(33)至行(37)間的程式碼用以計算第「E」(第五)欄的資料,此欄資料計算過去 TimePeriod天的

平均上漲天數,因此藉由一內部迴圈 (行(34)至行(36)間的程式碼)累計上漲天數總合,再除以TimePeriod,即得平均上漲天數比率,將之存入第五欄中(行(37))。由於,UpSum變數用以儲存過去TimePeriod天的上漲天數總合,在累計前必需設為 0(行(33))。行(39)至行(45)間的程式碼用以計算第「F」(第六)欄的資料,此欄資料為判斷買賣行動,若為 1

則買進(即當第「E」(第五)欄資料<=LowerBound時,設為 1)、若為 3則賣出(即當第「E」(第五)欄資料>

=UpBound時,設為 3),否則不買不賣(即當第「E」(第五)欄資料不滿足上述兩條件時,設為 2)。因此我們使用包含三種狀況的判斷結構,用以區別三種狀況的前提條件,以決定第「F」(第六)欄應該為 1

或 2或 3。在確定買賣決策後,在第「G」(第七)與第「H」(第八)欄分別可以調整隔天之股票與現金部位。行(47)至行(53)間的程式碼用以計算第「G」(第七)欄的資料(即股票部位)。若前一天(i-1)出現買訊

(第「F」(第六)欄的資料為 1),則投入第 i-1天的資金並以第 i天的開盤價(儲存於第「B」(第二)欄中)於隔日買進(即 Cells(i - 1, 8) / Cells(i, 2)之計算),並加入前一天(i-1)的股票部位(Cells(i - 1, 7)),可得今日(i)的股票部位;若前一天(i-1)出現「不買不賣」之訊號(第「F」(第六)欄的資料為 2),則今日(i)之股票部位等同於前一日(i-1)之股票部位;若前一天(i-1)出現賣訊(第「F」(第六)欄的資料為 3)(不為 1或 2的第三種狀況),則今日(i)之股票部位因全部賣出,將為 0。行(55)至行(62)間的程式碼用以計算第「H」(第八)欄的資料(即現金部位)。若前一天(i-1)出現買訊

(第「F」(第六)欄的資料為 1),則今日(i)之現金部位應全數買進,將為 0;若前一天(i-1)出現「不買不賣」之訊號(第「F」(第六)欄的資料為 2),則今日(i)之現金部位等同於前一日(i-1)之現金部位;若前一天(i-1)出現賣訊(第「F」(第六)欄的資料為 3)(不為 1或 2的第三種狀況),則將第 i-1天的股票以第 i天的開盤價(儲存於第「B」(第二)欄中)賣出(即 Cells(i - 1, 7) * Cells(i, 2)之計算),並加入前一天(i-1)的現金部位(Cells(i - 1, 8)),可得今日(i)的現金部位。行(65)用以計算期間的報酬率,計算方法為:(「期末股票+現金價值」-「期初現金價值」) /「期初

現金價值」(但由於「期初現金價值」為 1,因此在程式碼中無需再「/1」)。其中期末股票價值以「(最後一期的開盤價*股票部位)」求得。在此假設當日開盤價等於收盤價,此假設並不離譜,否則必須讀取最後一天收盤價資料計算。計算結果輸出到 TextBox5的文字框中。Format函數可用以設定數值輸出格式,"0.0000"表輸出格式為 1位整數、4位小數。

程式執行畫面如圖 4.2.7所示。

Page 6: 以Excel VBA進行回溯測試分析

圖 4.2.7系統執行結果