'################################################################################################### '# Indicator : Laguerre # '# Author : VERDESOFTS # '# Copyright : © VERDESOFTS # '# Website : www.verde-solution.com # '# E-mail : admin@verde-solution.com # '# Date : 10-Oct-2015 # '# Description : Laguerre is a powerful VertexFX client side VTL indicator from the Digital # '# Signal Processing family of indicators. # '# It is a bounded oscillator between 0 and 1 that tracks the market cycles. # '# In the first step, we calculate a Smoothed Moving Average based upon the Close # '# price using GAMMA smoothing constant. The current value of Smoothed Moving # '# Average is equal to (1 - GAMMA) multiplied by the current Close price plus # '# GAMMA multiplied by the previous value of the Smoothed Moving Average. # '# This step is repeated to calculate the third derivative of the Smoothed Moving # '# Average. # '# In the next step we calculate the cumulative sum of the difference between the # '# third derivative and the second derivative, and the second derivative and # '# first derivative. If the difference is positive, it is added to the positive # '# difference, and if the difference is negative, it is added to the negative # '# difference. # '# Finally, the Laguerre indicator value is the cumulative positive difference # '# divided by the cumulative negative difference. # '# The concept behind this indicator is to eliminate sideways movements and # '# noise. When the price is trending in a particular direction (either upwards or # '# downwards), the Laguerre value is moving in the direction of the trend. In a # '# uptrend the Laguerre value is rising and in a downtrend, the Laguerre value is # '# falling. # '# It oscillates between 0 and +1, with either extremes indicating a saturation # '# in the trend. # '# BUY - Enter BUY trade when the Laguerre indicator closes above 0.15 from # '# below. # '# SELL - Enter SELL trade when the Laguerre indicator closes below 0.75 from # '# above. # '# Inputs : 1) GAMMA - The smoothing constant used to smooth the derived values. # '# History : # '# 1.00 : Initial version. # '################################################################################################### '''###################### INPUT PARAMETERS #################################################### ''' All user input parameters are defined as constants so that they are not accidentally ''' changed in the code. Const GAMMA = 0.7 '''############################################################################################## ''' Indicator keys and data. Dim m_chartID ' To track the current chart ID Dim m_chartName ' To track the current chart Name Dim m_indID1 ' To track indicator series created by this script. Dim arrClose(), arrLaguerre() Dim BARS_COUNT ' To track the total number of bars on the current chart. Dim PROCESSING ' To track active processing activity. '########## System Constants ####### Const UNDEFINED = -987654321 ' Undefined value provided by VTL ' Price field constants for applied price. Const PF_CLOSE = 0 ' Price Series : Close Const PF_OPEN = 1 ' Price Series : Open Const PF_HIGH = 2 ' Price Series : High Const PF_LOW = 3 ' Price Series : Low Const PF_MEDIAN = 4 ' Price Series : Median (H+L)/2 Const PF_TYPICAL = 5 ' Price Series : Typical (H+L+C)/3 Const PF_WEIGHTED = 6 ' Price Series : Weighted (H+L+2C)/4 Const PF_VOLUME = 10 ' Price Series : Volume Const VOL_DEFAULT = 100 ' Default Volume when Volume is missing ' Color Constants Const COLOR_MAGENTA = 16711935 ' Magenta Const COLOR_SILVER = 16443622 ' Silver '//////////////////////////////////////////////////////////////////////////////////////// ' Main '//////////////////////////////////////////////////////////////////////////////////////// Public Sub main() While (PROCESSING) Wend PROCESSING = True BARS_COUNT = 0 m_chartID = ChartID() m_chartName = ChartSymbol(CLng(m_chartID)) updateBuffers performCalculations 1 ' Add indicator series to chart. m_indID1 = AddCustomIndicator(0, arrLaguerre, 1, True) SetSeriesStyle 0, CStr(m_indID1), LINE_CHART LineColor 0, CStr(m_indID1), COLOR_MAGENTA LineWeight 0, CStr(m_indID1), 2 Dim subWindow subWindow = CLng(GetSubwindow(0, CStr(m_indID1))) SetChartScale CLng(m_chartID), CLng(subWindow), CDbl(1.05), CDbl(-0.05) ' Add 0 dotted horizontal line AddDottedHLine "lg0", CLng(subWindow), COLOR_SILVER, 0.00 AddDottedHLine "lg1", CLng(subWindow), COLOR_SILVER, 0.15 AddDottedHLine "lg2", CLng(subWindow), COLOR_SILVER, 0.45 AddDottedHLine "lg3", CLng(subWindow), COLOR_SILVER, 0.75 AddDottedHLine "lg4", CLng(subWindow), COLOR_SILVER, 1.00 PROCESSING = False End Sub '//////////////////////////////////////////////////////////////////////////////////////// ' AddDottedHLine '//////////////////////////////////////////////////////////////////////////////////////// Private Sub AddDottedHLine(Byval name, Byval subWindow, Byval color, Byval value) If( AddObject(0, CStr(name), 15, CLng(subWindow), 0, CDbl(value)) ) Then ObjectSet 0, CStr(name), 3, CLng(color) ObjectSet 0, CStr(name), 5, 2 End If End Sub '//////////////////////////////////////////////////////////////////////////////////////// ' OnTick '//////////////////////////////////////////////////////////////////////////////////////// Public Sub OnTick(symbolName) If( PROCESSING ) Then Exit Sub If( symbolName <> ChartSymbol(0) ) Then Exit Sub If( CLng(BARS_COUNT) <> CLng(Bars(0)) ) Then Exit Sub ' Write your OnTick code from here arrClose(CLng(BARS_COUNT)) = getPriceValue(PF_CLOSE, CLng(BARS_COUNT)) performCalculations CLng(BARS_COUNT) ' Write to chart update code from here ObjectSeriesSetValue 0, CStr(m_indID1), CLng(BARS_COUNT), CDbl(arrLaguerre(BARS_COUNT)) End Sub '//////////////////////////////////////////////////////////////////////////////////////// ' OnCalculate '//////////////////////////////////////////////////////////////////////////////////////// Public Sub OnCalculate(symbol, symbolPeriod, openVal, highVal, lowVal, closeVal) If (PROCESSING) Then Exit Sub If( symbol <> ChartSymbol(0) ) Then Exit Sub PROCESSING = True updateBuffers performCalculations 1 SetIndicatorData 0, CStr(m_indID1), CDbl(arrLaguerre(BARS_COUNT)) PROCESSING = False End Sub '//////////////////////////////////////////////////////////////////////////////////////// ' updateBuffers ' Update data buffers and build / perform calculations as required. ' Loads all the required data for the indicator. This function is called during ' initialization and during OnCalculate '//////////////////////////////////////////////////////////////////////////////////////// Private Sub updateBuffers() loadPriceSeries PF_CLOSE, arrClose loadPriceSeries PF_CLOSE, arrLaguerre Dim i For i = 1 To CLng(Bars(0)) arrLaguerre(i) = 0.0 Next ' Make sure this is the last line of the function BARS_COUNT = CLng(Bars(0)) End Sub '//////////////////////////////////////////////////////////////////////////////////////// ' performCalculations ' Perform calculations for the specified range on the buffer. ' E.g. if startBar = 90, it performs calculations from the 90th-bar to the latest bar. '//////////////////////////////////////////////////////////////////////////////////////// Private Sub performCalculations(Byval startBar) Dim i, L0, L1, L2, L3, L0A, L1A, L2A, L3A, LRSI, CU, CD L0 = 0: L1 = 0: L2 = 0: L3 = 0: L0A = 0: L1A = 0: L2A = 0: L3A = 0: LRSI = 0 For i = CLng(startBar) To CLng(BARS_COUNT) L0A = L0 L1A = L1 L2A = L2 L3A = L3 L0 = (1 - GAMMA) * arrClose(i) + GAMMA * L0A L1 = - GAMMA * L0 + L0A + GAMMA *L1A L2 = - GAMMA * L1 + L1A + GAMMA *L2A L3 = - GAMMA * L2 + L2A + GAMMA *L3A CU = 0 CD = 0 If (L0 >= L1) Then CU = L0 - L1 Else CD = L1 - L0 End If If (L1 >= L2) Then CU = CU + L1 - L2 Else CD = CD + L2 - L1 End if If (L2 >= L3) Then CU = CU + L2 - L3 Else CD = CD + L3 - L2 End If If (CU + CD <> 0) Then LRSI = CU / (CU + CD) arrLaguerre(i) = LRSI Next End Sub '//////////////////////////////////////////////////////////////////////////////////////// ' loadPriceSeries '//////////////////////////////////////////////////////////////////////////////////////// Private Sub loadPriceSeries(Byval priceField, Byref array()) ' Price Field - Close(0), Open(1), High(2), Low(3), Median(4), Typical(5), Weighted(6) Dim totalBars totalBars = CLng(Bars(0)) Erase array CopyClose 0, 1, Bars(0), array Dim arrHigh(), arrLow(), arrClose() If( priceField = PF_OPEN ) Then ' OPEN CopyOpen 0, 1, Bars(0), array Elseif( priceField = PF_HIGH ) Then ' HIGH CopyHigh 0, 1, Bars(0), array Elseif( priceField = PF_LOW ) Then ' LOW CopyLow 0, 1, Bars(0), array Elseif( priceField = PF_MEDIAN ) Then ' MEDIAN CopyHigh 0, 1, Bars(0), arrHigh CopyLow 0, 1, Bars(0), arrLow For i = 1 To totalBars array(i) = CDbl( (CDbl(arrHigh(i)) + CDbl(arrLow(i))) / 2.0) Next Elseif( priceField = PF_TYPICAL OR priceField = PF_WEIGHTED ) Then 'TYPICAL OR WEIGHTED CopyHigh 0, 1, Bars(0), arrHigh CopyLow 0, 1, Bars(0), arrLow CopyClose 0, 1, Bars(0), arrClose For i = 1 To totalBars If( priceField = PF_TYPICAL ) Then array(i) = (CDbl(arrHigh(i)) + CDbl(arrLow(i)) + CDbl(arrClose(i))) / 3.0 Elseif( priceField = PF_WEIGHTED ) Then array(i) = (CDbl(arrHigh(i)) + CDbl(arrLow(i)) + 2.0 * CDbl(arrClose(i)))/ 4.0 End If Next Elseif( priceField = PF_VOLUME ) Then ' VOLUME CopyClose 0, 1, Bars(0), array For i = 1 To totalBars array(i) = CLng(VOL_DEFAULT) Next Else ' CLOSE CopyClose 0, 1, Bars(0), array End If End Sub '//////////////////////////////////////////////////////////////////////////////////////// ' getPriceValue ' Returns the specified price (or volume) field value for the specified bar. ' E.g. if priceField is PF_OPEN, and barNum = 9, it returns the Open price of the 9th ' bar. '//////////////////////////////////////////////////////////////////////////////////////// Private Function getPriceValue(Byval priceField, Byval barNum) ' Price Field - Close(0), Open(1), High(2), Low(3), Median(4) Dim result If( priceField = PF_OPEN ) Then ' OPEN result = GetOpen(0, CLng(barNum)) Elseif( priceField = PF_HIGH ) Then ' HIGH result = GetHigh(0, CLng(barNum)) Elseif( priceField = PF_LOW ) Then ' LOW result = GetLow(0, CLng(barNum)) Elseif( priceField = PF_MEDIAN ) Then ' MEDIAN result = (CDbl(GetHigh(0, CLng(barNum))) + CDbl(getLow(0, CLng(barNum)))) / 2.0 Elseif( priceField = PF_TYPICAL ) Then ' TYPICAL result = (CDbl(GetHigh(0, CLng(barNum))) + CDbl(getLow(0, CLng(barNum)) + CDbl(getClose(0, CLng(barNum))))) / 3.0 Elseif( priceField = PF_WEIGHTED ) Then ' WEIGHTED result = (CDbl(GetHigh(0, CLng(barNum))) + CDbl(getLow(0, CLng(barNum)) + 2.0 * CDbl(getClose(0, CLng(barNum))))) / 4.0 Elseif( priceField = PF_VOLUME ) Then result = CDbl(VOL_DEFAULT) Else ' CLOSE result = GetClose(0, CLng(barNum)) End If getPriceValue = CDbl(result) End Function '//////////////////////////////////////////////////////////////////////////////////////// ' OnInit '//////////////////////////////////////////////////////////////////////////////////////// Public Sub OnInit() End Sub '//////////////////////////////////////////////////////////////////////////////////////// ' OnDeInit '//////////////////////////////////////////////////////////////////////////////////////// Public Sub OnDeInit() ObjectDelete 0, CStr(m_indID1) ObjectDelete 0, "lg0" ObjectDelete 0, "lg1" ObjectDelete 0, "lg2" ObjectDelete 0, "lg3" ObjectDelete 0, "lg4" BARS_COUNT = 1 End Sub '//////////////////////////////////////////////////////////////////////////////////////// ' AllDataLoaded '//////////////////////////////////////////////////////////////////////////////////////// Public Sub AllDataLoaded() End Sub '//////////////////////////////////////////////////////////////////////////////////////// ' AccountSelected '//////////////////////////////////////////////////////////////////////////////////////// Public Sub AccountSelected(accountNumber) End Sub '//////////////////////////////////////////////////////////////////////////////////////// ' OnOrderTrade '//////////////////////////////////////////////////////////////////////////////////////// Public Sub OnOrderTrade(actionType, orderID, returnValue) End Sub '//////////////////////////////////////////////////////////////////////////////////////// ' OnPositionTrade '//////////////////////////////////////////////////////////////////////////////////////// Public Sub OnPositionTrade(actionType, ticketID) End Sub '//////////////////////////////////////////////////////////////////////////////////////// ' OnManageOrdersReceived '//////////////////////////////////////////////////////////////////////////////////////// Public Sub OnManageOrdersReceived(manageOrders) End Sub '//////////////////////////////////////////////////////////////////////////////////////// ' OnTimer '//////////////////////////////////////////////////////////////////////////////////////// Public Sub OnTimer() End Sub