2013년 2월 14일 목요일

Excel에서 HTS DDE 활용하기 5 - Chart와 지표 VI

※ Elliott Pattern Helper Add In
  • Download Add In for Excel 2007 
  • Download Add In for Excel 2003 


  지난 글에서 몇몇 기술적 지표의 구현을 위한 기초 작업 완료했습니다. 그렇다면 지금까지 작성해왔던 VBA 프로그램과 통합해 보아야 겠지요.

  우선 시나리오를 정리하면  두 개입니다. 하나는 지표를 축적하는 것이고, 다른 하나는 차트에 출력하는 것인데, 모두 DDE 이벤트를 반영해야 합니다. 즉, 축적되는 지표 자체나 이를 출력하는 차트 또한 DDE와 연동되어 update되어야 합니다.
  ▷ 시나리오 1. 지표 축적
  •  'Schedule' 버튼을 클릭하면 축적할 지표를 선택할 수 있는 폼이 팝업된다. ※ 'FSchedule' 폼에 새로운 페이지를 추가하여 사용합니다.
  •  지표를 선택하면 해당 지표의 기간(period)을 설정하는 텍스트 상자와 이동평균 사용시 단순이동평균 사용을 지시하는 체크박스가 활성화된다. ※ 지수이동평균이 default인데 이를 단순이동평균으로 변경할 경우에 사용합니다.
  •  'OK' 버튼을 클릭하면 선택된 지표가 축적된다. ※ 'FSchedule' 폼을 통해 선택된 (종목×시간단위)의 캔들정보 시트에 축적됩니다. 
  •  DDE 이벤트에 따라 지표가 refresh된다.
  시나리오 2. 지표 출력
  • 'Chart' 버튼을 클릭하면 세 가지 지표 중 하나를 선택하는 폼이 팝업된다.
  • 기간을 설정하고 'OK' 버튼을 클릭하면 차트출력 시트("CHARTS")에 지표를 포함하는 캔들차트가 생성된다. ※ 기간은 '시나리오 1'에서 지정한 시간과 다를 수 있습니다.
  • DDE 이벤트에 따라 차트가 refresh된다.
      
▶ (시나리오 1). 'FSchedule' 수정 

  시나리오 1을 위해 기존에 작성한 폼 'FSchedule'을 수정하겠습니다. 엑셀에서 메뉴 '개발 도구' → 'Visual Basic'을 선택하거나 키보드의 'Alt + F11'을 눌러 VBA 편집창을 띄웁니다.
  
  VBAProject 트리 목록에서 'FSchedule'의 Context 메뉴 → '개체 보기'를 선택한 후 다중 페이지의 Context 메뉴 → '새 페이지'를 클릭하여 페이지를 생성합니다. 페이지의 Caption은 적절히 입력하십시요.

  지표를 선택하기 위한 콤보상자를 생성합니다. 도구상자의 콤보상자를 선택하고(그림 1의 1), 새로 생성한 페이지에 위치시킨 후(그림 1의 2), 이름을 'ComboBoxTI'로 수정합니다(그림 1의 3).

그림 1. 지표 선택을 위한 콤보상자 생

  지표의 기간 설정을 위한 텍스트 상자 세 개를 생성하겠습니다. 도구상자의 텍스트 상자를 선택하고(그림 2-1의 1), 적절한 크기로 생성한 후(그림 2-1의 2), 이름을 'TextBoxP1'으로 수정합니다(그림 2-1의 3).
  
그림 2-1. 지표의 기간 설정을 위한 텍스트 상자 생성 1
  
  다음 그림 2-2와 같이 동일한 방법으로 'TextBoxP2'와 'TextBoxP3'를 생성하고 레이블을 적절히 입력합니다.
  
그림 2-2. 지표의 기간 설정을 위한 텍스트 상자 생성 2
  
  지표 계산 시 지수이동평균이 아닌 단순이동평균을 사용하기 위한 체크박스를 생성합니다. 도구상자를 선택하고 체크박스를 선택한 후(그림 3의 1), 다음 그림과 같이 생성합니다(그림 3의 2). 이름은 'CheckBoxSMA'로 합니다(그림 3의 3). Caption은 제거하고 레이블을 적절히 입력합니다.

그림 3. 단순이동평균 지정을 위한 체크박스 생성
 
  지표를 추가하기 위한 버튼을 생성합니다. 도구상자의 명령단추를 선택하고(그림 4의 1), 아래 그림과 같이 생성합니다(그림 4의 2). 버튼 이름은 'ButtonAdd'로 수정합니다(그림 4의 3).  Caption은 적절히 입력하십시요.
  
그림 4. 지표를 추가하기 위한 버튼 생성
  
  추가된 지표를 표시하기 위한 목록상자를 추가합니다. 도구상자에서 목록상자를 선택하고(그림 5의 1), 다음 그림과 같이 생성합니다(그림 5의 2). 목록상자 이름은 'ListBoxTI'로 합니다(그림 5의 3). 레이블은 적절히 추가하십시요.

그림 5. 선택된 지표를 표시하는 목록상자 생성
 
  위 그림 1에서 5까지 추가된 UI 콘트롤들의 이벤트 매크로를 작성하겠습니다. 

  먼저 선택 가능한 지표를 'ComboBoxTI'의 초기화 코드로 입력합니다. 더불어 콤보상자 'ComboBoxTI'를 통해 선택된 항목(지표)이 달라질 때마다 입력해야 할 기간(period)의 개수가 달라집니다. 이를 반영하기 위한 코드를 입력하겠습니다.

  ※ (폼 'FSchedule'의 수정 후 'UserForm_Initialize' 소스)
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Private Sub UserForm_Initialize()
        ComboBoxTS.AddItem "09:00:00"
        ComboBoxTS.AddItem "10:00:00"
        ComboBoxTS.AddItem "11:00:00"
        ComboBoxTS.AddItem "12:00:00"
        ComboBoxTS.AddItem "13:00:00"
        ComboBoxTS.AddItem "14:00:00"
        ComboBoxTS.AddItem "15:00:00"
        ComboBoxTS.Text = "09:00:00"
    
        ComboBoxTE.AddItem "09:00:00"
        ComboBoxTE.AddItem "10:00:00"
        ComboBoxTE.AddItem "11:00:00"
        ComboBoxTE.AddItem "12:00:00"
        ComboBoxTE.AddItem "13:00:00"
        ComboBoxTE.AddItem "14:00:00"
        ComboBoxTE.AddItem "15:00:00"
        ComboBoxTE.Text = "15:00:00"
    
        ComboBoxCT.AddItem "5분", 0
        ComboBoxCT.AddItem "15분", 1
        ComboBoxCT.AddItem "60분", 2
        ComboBoxCT.AddItem "일", 3
        ComboBoxCT.ListIndex = 0
    
        s_list = getStockList()
        Set s_code = New Collection
        For i = LBound(s_list, 1) To UBound(s_list, 1)
            If s_list(i, 1) <> "" Then
                s_code.Add s_list(i, 1), s_list(i, 2)
                ComboBoxSN.AddItem s_list(i, 2), i - 1
            End If
        Next i
        ComboBoxSN.ListIndex = 0
    
        s_list = Split(sheets_cs(xlNullString), ",")
        For i = LBound(s_list) To UBound(s_list)
            ListBoxSC.AddItem Replace(s_list(i), "-", " ")
        Next i
    
        ComboBoxTI.AddItem "MACD", 0
        ComboBoxTI.AddItem "RSI", 1
        ComboBoxTI.AddItem "OBV", 2
        ComboBoxTI.AddItem "FRTL", 3
        ComboBoxTI.AddItem "PFTW", 4
        Call DisableAllP
    
        ListBoxTI.AddItem "MACD (지수 5 34 5)"
        ListBoxTI.AddItem "RSI (지수 13)"
        ListBoxTI.AddItem "OBV (지수 9)"
        ListBoxTI.AddItem "FRTL (7)"
        ListBoxTI.AddItem "PFTW"
    End Sub

    Private Sub DisableAllP()
        TextBoxP1.Value = xlNullString
        TextBoxP2.Value = xlNullString
        TextBoxP3.Value = xlNullString
        TextBoxP1.Enabled = False
        TextBoxP2.Enabled = False
        TextBoxP3.Enabled = False
    End Sub

    Private Sub EnableAllP()
        TextBoxP1.Enabled = True
        TextBoxP2.Enabled = True
        TextBoxP3.Enabled = True
    End Sub

    Private Sub EnableP1()
        TextBoxP2.Value = xlNullString
        TextBoxP3.Value = xlNullString
        TextBoxP1.Enabled = True
        TextBoxP2.Enabled = False
        TextBoxP3.Enabled = False
    End Sub

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  ☞ 하이라이트 된 부분이 추가된 코드입니다. 
  
  콤보상자 'ComboBoxTI'에서 선택된 값에 따라 텍스트 상자 'TextBoxP1', 'TextBoxP2' 및 'TextBoxP3'의 초기화를 다르게 설정할 것입니다. 폼 'FSchedule'의 개체편집 모드에서 콤보상자 'ComboBoxTI'를 더블클릭하면 소스코드 편집 모드로 바뀌면서 'ComboBoxTI_Change' 매크로의 뼈대가 생성됩니다. 아래 소스를 참고하여 입력하십시요.
  
  ※ ('ComboBoxTI_Change' 소스)
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Private Sub ComboBoxTI_Change()
        Select Case ComboBoxTI.ListIndex
        Case 0
            Call EnableAllP
            TextBoxP1.value = 5
            TextBoxP2.value = 34
            TextBoxP3.value = 5
        Case 1
            Call EnableP1
            TextBoxP1.value = 13
        Case 2
            Call EnableP1
            TextBoxP1.value = 9
        Case 3
            Call EnableP1
            TextBoxP1.value = 7
        Case 4
            Call DisableAllP
        End Select
    End Sub

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

  ☞ 선택된 지표에 따라 기간(period) 지정을 위한 텍스트 상자를 다르게 초기화합니다.
 
  지표와 기간을 지정한 후 'Add' 버튼을 클릭하면 선택지표 목록상자 'ListBoxTI'에 목록이 추가되도록 해야 합니다. 폼 'FSchedule'의 개체편집 모드에서 'ButtonAdd'를 더블클릭하면 소스코드 편집 모드로 바뀌면서 'ButtonAdd_Click' 매크로의 뼈대가 생성됩니다. 아래 소스를 참고하여 입력하십시요.
  
  ※ ('ButtonAdd_Click' 이벤트 소스)
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Private Sub ButtonAdd_Click()
        Dim ns As String
        On Error GoTo Skip:
     
        Select Case ComboBoxTI.ListIndex
        Case 0
            ns = "MACD ("
            If TextBoxP1.value = xlNullString Then GoTo Skip:
            If CInt(TextBoxP1.value) > 0 Then
                ns = ns & TextBoxP1.value & " "
            Else
                GoTo Skip:
            End If
            If CInt(TextBoxP2.value) > 0 Then
                ns = ns & TextBoxP2.value & " "
            Else
                GoTo Skip:
            End If
            If Not TextBoxP3.value = xlNullString Then
                ns = ns & CInt(TextBoxP3.value) & ")"
            Else
                ns = Left(ns, Len(ns) - 1)
                ns = ns & ")"
            End If
        Case 1
            ns = "RSI ("
            If CInt(TextBoxP1.value) > 0 Then
                ns = ns & TextBoxP1.value & ")"
            Else
                GoTo Skip:
            End If
        Case 2
            ns = "OBV"
            If Not TextBoxP1.value = xlNullString Then
             ns = ns & " (" & CInt(TextBoxP1.value) & ")"
            Else
                GoTo SkipMA:
            End If
        Case 3
            ns = "FRTL ("
            If CInt(TextBoxP1.value) > 0 Then
                ns = ns & TextBoxP1.value & ")"
            Else
                GoTo Skip:
            End If
        Case 4
            ns = "PFTW"
        Case Else
            GoTo Skip:
        End Select
     
        If ComboBoxTI.value <> "FRTL" Or ComboBoxTI.value <> "PFTW" Then
            If CheckBoxSMA.value = True Then
                ns = Replace(ns, "(", "(단순 ")
            Else
                ns = Replace(ns, "(", "(지수 ")
            End If
        End If
     
    SkipMA:
        For i = 0 To ListBoxTI.ListCount - 1
            If ListBoxTI.List(i) = ns Then GoTo Skip:
        Next i
        ListBoxTI.AddItem ns
    Skip:

    End Sub

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

  ☞ 'MACD (지수 5 34 5)', 'RSI (단순 14)'와 같은 형태의 문자열로 목록상자 'ListBoxTI'에 추가됩니다.  
  
  선택지표 목록상자 'ListBoxTI'에 추가된 목록 중의 특정 항목을 더블클릭하면 해당 항목의 선택이 취소되면서 'ListBoxTI'에서 사라지도록 할 것입니다. 아래 'ListBoxTI_DblClick' 소스를 'ComboBoxTI_Change' 코드 밑에 입력하십시요.
  
  ※ ('ListBoxTI_DblClick' 이벤트 소스)
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Private Sub ListBoxTI_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
        If Not ListBoxTI.ListIndex < 0 Then _
            ListBoxTI.RemoveItem ListBoxTI.ListIndex
    End Sub

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

  
  폼 'FSchedule'의 'OK' 버튼 이벤트 매크로를 수정해야 합니다. 기존 소스는 캔들정보를 축적할 종목 리스트와 스케줄 시각을 전달하면서 'onSchedule'을 호출합니다. 선택된 지표 목록을 함께 전달하도록 수정합니다.
  
  ※ (수정 후 'ButtonOK_Click' 소스)
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Private Sub ButtonOK_Click()
        Dim s_list As String    'comma separated selected stock list
        Dim i_list As String    'comma separated selected indicator list
     
        Me.Hide
        For i = 0 To ListBoxSC.ListCount - 1
            sitem = ListBoxSC.List(i)
            sn = Split(sitem, " ")
            sc = s_code.Item(sn(LBound(sn)))
            sitem = Replace(sitem, " ", "(" & sc & ")")
            s_list = s_list & sitem & ","
        Next i
     
        For i = 0 To ListBoxTI.ListCount - 1
            i_list = i_list & ListBoxTI.List(i) & ","
        Next i
     
        If Len(s_list) > 0 Then
            s_list = Left(s_list, Len(s_list) - 1)
            If Len(i_list) > 0 Then i_list = Left(i_list, Len(i_list) - 1)
            Call onSchedule(ComboBoxTS.Text, ComboBoxTE.Text, _
                            s_list, i_list)
        End If
    End Sub

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

  ☞ 하이라이트 된 부분이 수정된 곳입니다. 
  ☞ 'i_list' 변수가 'MACD (지수 5 34 5),RSI (단순 14)'와 같이 comma-separated string 형태로 선택지표 목록을 저장하여 'onSchedule'에 전달됩니다.
  
  'FSchedule' 폼의 수정은 완료되었습니다.
  ※ 'FSchedule' 폼 소스


▶ (시나리오 1). Module 수정 

  폼 'FSchedule'의 'OK' 버튼 클릭 시 호출되는  'onSchedule'을 수정합니다.

  ※ (수정 후 'onSchedule' 소스)
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Sub onSchedule(ts, te, sc, il)
        Call registerLinks
        Call prepareSheet(sc, il)
     
        If Time > TimeValue(ts) And Time < TimeValue(te) Then
            Application.OnTime Now, "Start_Click"
        Else
            Application.OnTime TimeValue(ts), "Start_Click"
        End If
        Application.OnTime TimeValue(te), "Stop_Click"
    End Sub

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  ☞ 선택지표 목록(comma-separated string, 'il')을 저장하는 인자가 추가되었습니다.

  마찬가지로 'onSchedule'이 'prepareSheet'을 호출할 때 선택지표 목록을 추가로 넘겨주도록 수정합니다. 함수 'prepareIndicators'를 신규로 작성하고, 'prepareSheet'는 넘겨받은 지표 목록을 인자로 넘기면서 'prepareIndicators'를 호출하도록 하겠습니다.
 
  ※ (수정 후 'prepareSheet' 소스)
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Function prepareSheet(slist, ilist)
        Dim xlSheet As Worksheet
        Dim s_arr As Variant
        On Error GoTo EH_prepareSheet:
        dde_sheet = ActiveSheet.Name
     
        Call prepareIndicators(ilist, True)       'for indicators
        s_arr = Split(slist, ",")
        s_cnt = UBound(s_arr) - LBound(s_arr) + 1
        ReDim ss_list(1 To s_cnt, 1 To 2)
        Set feeders = New Collection
     
        For i = LBound(s_arr) To UBound(s_arr)
            sn = s_arr(i)
            pospl = InStr(sn, "(")
            pospr = InStr(sn, ")")
            cu = Right(sn, Len(sn) - pospr)
            s_code = Mid(sn, pospl + 1, pospr - pospl - 1)
            If s_code = Empty Or s_code = "" Then GoTo NextLoop:
         
            sh_name = Left(sn, pospl - 1)
            If sh_name = Empty Or sh_name = "" Then sh_name = s_code
            sh_name = sh_name & "-" & cu
         
            ss_list(i - LBound(s_arr) + 1, 1) = s_code
            ss_list(i - LBound(s_arr) + 1, 2) = sh_name
     
            Dim cfeeder As CCandleFeeder
            Set cfeeder = New CCandleFeeder
            cfeeder.StockCode = s_code
            cfeeder.CandleSheet = sh_name
            cfeeder.DDEsheet = dde_sheet
            cfeeder.CHTsheet = CHART_POSTFIX
            cfeeder.TIndicator = assignIndicators(s_code, sh_name)
            feeders.Add cfeeder, s_code
         
            If Not sheetExist(sh_name) Then
                Set xlSheet = Worksheets.Add(After:=Worksheets(Worksheets.Count))
                xlSheet.Name = sh_name
             
                With xlSheet
                    .Cells(1, 1).value = "일자 / 시간"
                    .Cells(1, 2).value = "시가"
                    .Cells(1, 3).value = "고가"
                    .Cells(1, 4).value = "저가"
                    .Cells(1, 5).value = "종가"
                    .Cells(1, 6).value = "거래량"
                End With
            End If
    NextLoop:
        Next i
     
        Set xlSheet = Nothing
        Exit Function
     
    EH_prepareSheet:
        MsgBox "Error(" & Err.Number & ") " & Err.Description & " [prepareSheet]"
        Err.Raise Err.Number, "prepareSheet", Err.Description
    End Function

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  ☞ 인자(선택지표 목록, 'ilist')가 추가되었습니다.
  ☞ 'prepareIndicators' 함수를 호출하는 코드가 추가되었습니다.
  ☞ 지난 글에서 'CCandleFeeder' 클래스에 멤버 변수(property) 'pTIndicator'를 추가했습니다. 이를 초기화하기 위해 함수 'assignIndicators'를 호출합니다. 

  
  신규 함수 'prepareIndicators'와 'assignIndicators'를 작성하겠습니다.

   'prepareIndicators'는 폼 'FSchedule'을 통해 입력받은 지표목록을 구조체 'indicator_t'의 배열로 저장함으로써 다른 함수에서 참조할 수 있도록합니다. 아래 소스를 복사하여 입력하십시요.


  ※ (함수 'prepareIndicators' 소스)

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Function prepareIndicators(ilist, b)
        Dim indi_t As indicator_t
        On Error GoTo EH_prepareIndicators:
     
        If b Then
            si_list = Split(ilist, ",")
            If UBound(si_list) < 0 Then Exit Function
            ReDim it_arr(LBound(si_list) To UBound(si_list))
         
            For i = LBound(si_list) To UBound(si_list)
                indi_t = indicator_type(si_list(i))
                If indi_t.i_type <> 0 Then it_arr(i) = indi_t
    NextLoop:
            Next i
        Else
            On Error Resume Next
            ub = UBound(si_list)
            If Err.Number = 13 Then si_list = Split(ilist, ",")
            On Error GoTo 0
            For i = LBound(si_list) To UBound(si_list)
                If ilist = si_list(i) Then Exit Function
            Next i
         
            indi_t = indicator_type(ilist)
            If indi_t.i_type <> 0 Then
                ReDim Preserve si_list(LBound(si_list) To UBound(si_list) + 1)
                si_list(UBound(si_list)) = ilist
                ReDim Preserve it_arr(LBound(si_list) To UBound(si_list))
                it_arr(UBound(it_arr)) = indi_t
             
                For i = 1 To UBound(ss_list)
                    Dim fdr As CCandleFeeder
                    On Error Resume Next
                    Set fdr = feeders.Item(ss_list(i, 1))
                    If Err.Number = 5 Then GoTo Continue:
                    On Error GoTo 0
                    If Not fdr Is Nothing Then _
                        fdr.TIndicator = assignIndicators(ss_list(i, 1), ss_list(i, 2))
    Continue:
                Next i
            End If
        End If
     
        Exit Function
    EH_prepareIndicators:
        MsgBox "Error(" & Err.Number & ") " & Err.Description & " [prepareIndicators]"
        Err.Raise Err.Number, "prepareIndicators", Err.Description
    End Function


    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  ☞ 지표목록(comma-separated string)을 구조체('indicator_t') 배열로 저장합니다.
  ☞ 'it_arr'이 'indicator_t' 구조체 배열입니다. 전역변수로 선언해야 합니다. 'prepareSheet' 함수가 있는 모듈의 선언부에 'Private it_arr() As indicator_t' 라인을 추가하십시요.
  ☞ 'si_list'는 지표목록을 string 배열로 저장하기 위한 전역변수입니다. 'prepareSheet' 함수가 있는 모듈의 선언부에 'Private si_list As Variant' 라인을 추가하십시요.
  ☞ 지표 string(예: 'MACD (지수 5 34 6)')을 'indicator_t'로 변환하기 위해 함수 'indicator_type'을 호출합니다. 아래 소스를 참고하십시요.

  ※ (함수 'indicator_type' 소스) 
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Function indicator_type(istr) As indicator_t 
        Dim indi_t As indicator_t, t_arr As Variant, p_arr() As Integer
        t_arr = Split(istr, " ")
        lB = LBound(t_arr)
        ub = UBound(t_arr)
        If ub < 0 Then Exit Function
     
        Dim mtp As ma_t
        mtp = 0
     
        If InStr(istr, "지수") > 1 Then
            mtp = ma_e                  'default MA type = EMA
        ElseIf InStr(istr, "단순") > 1 Then
            mtp = ma_s
        End If
     
        Select Case t_arr(lB)
        Case "MACD"
            indi_t.i_type = 2 ^ 1
            ReDim p_arr(1 To ub - lB - 1)
            For j = lB + 2 To ub
                p_arr(j - lB - 1) = CInt(Replace(t_arr(j), ")", ""))
            Next j
            indi_t.peri = p_arr
            If ub - lB - 1 > 2 Then indi_t.i_type = indi_t.i_type + 1
        Case "RSI"
            indi_t.i_type = 2 ^ 2
            ReDim p_arr(1 To 1)
            p_arr(1) = CInt(Replace(t_arr(ub), ")", ""))
            indi_t.peri = p_arr
        Case "OBV"
            indi_t.i_type = 2 ^ 3
            If mtp > 0 Then
                ReDim p_arr(1 To 1)
                p_arr(1) = CInt(Replace(t_arr(ub), ")", ""))
                indi_t.peri = p_arr
                indi_t.i_type = indi_t.i_type + 1
            End If
        Case "FRTL"
            indi_t.i_type = 2 ^ 4
            ReDim p_arr(1 To 1)
            p_arr(1) = CInt(Replace(Replace(t_arr(ub), ")", ""), "(", ""))
            indi_t.peri = p_arr
        Case "PFTW"
            indi_t.i_type = 2 ^ 5
        Case Else
            Exit Function
        End Select
     
        indi_t.m_type = mtp
        indicator_type = indi_t
    End Function

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''


  'assignIndicators' 함수는 주어진 (종목×캔들정보 시트)에 대응하는 'CCandleFeeder' 클래스의 'pTIndicator' 멤버('CStockIndicator' 배열)를 초기화하기 위한 것입니다. 아래 소스를 참고하십시요.

  ※ (함수 'assignIndicators' 소스)
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Function assignIndicators(s_code, c_sheet) As Variant
        Dim indi_arr() As CStockIndicator
      
        On Error GoTo EH_assignIndicators:
        If UBound(it_arr) < 0 Then Exit Function
        ReDim indi_arr(LBound(it_arr) To UBound(it_arr))
      
        icol = 7 'indicator column
        For i = LBound(it_arr) To UBound(it_arr)
            Dim sindicator As CStockIndicator, tArr As Variant
          
            Set sindicator = New CStockIndicator
            sindicator.CandleSheet = c_sheet
            sindicator.Indicator = it_arr(i).i_type
            sindicator.MA = it_arr(i).m_type
            sindicator.Peroids = it_arr(i).peri
            sindicator.Col = icol 'sindicator.init()
            icol = sindicator.init()
            Set indi_arr(i) = sindicator
    NextLoop:
        Next i
      
    MyExit:
        assignIndicators = indi_arr
        Debug.Print "assignIndicator total" & UBound(indi_arr) - LBound(indi_arr) + 1
        Exit Function
    EH_assignIndicators:
        If Err.Number = 8911 Then
            Debug.Print "Error(8911) " & Err.Source
            Err.Clear
            GoTo NextLoop:
        End If
        Debug.Print "Error(" & Err.Number & ") " & Err.Description & " [assignIndicators]"
        GoTo MyExit:
    End Function

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

  ☞ 'CStockIndicator' 오브젝트를 생성하면서 'init'을 호출하여 지표 초기계산을 완료합니다.

  

  시나리오 1의 구현이 완료되었습니다. 파일을 저장한 후 테스트해 보겠습니다.

그림 6. 테스트

  'Schedule' 버튼을 클릭하여 'FSchedule' 폼을 팝업시키고 위의 그림 6과 같이 지정하여 'OK' 버튼을 클릭하니 그림 7의 결과를 얻을 수 있었습니다.


그림 7. 테스트 결과

  ※ 현재까지 완성된 엑셀 파일입니다.

  ※ 다음 글에서 '시나리오 2'를 진행하겠습니다.
 

댓글 없음:

댓글 쓰기