# Public and for release, CBEC v3.2.06 Build 4255+ [12th November, 2025] # # Copyright(c) Ivyware Pty Ltd 2019-25 (all rights reserved) # MELBOURNE, VICTORIA, AUSTRALIA, 3000 # # This file is provided as-is by Ivyware Pty Ltd. No claims are made # as to fitness for any particular purpose. No warranties of any kind # are expressed or implied. The recipient agrees to determine # applicability of information provided. # # Ivyware hereby grants the right to freely use the information # supplied in this file for the creation of Python automation scripts # supporting the Chartboard Application, and to make copies of this # file in any form for internal or external distribution as long as # this notice remains attached. # # No waranty or suitability for purpose is implied. # # Simple Python Scanner script using fitted Reversals objects to generate # a list of stocks with bullish buy signals. # NOTES: Download latest version from # https://www.ivyware.com.au/PythonScripts/SampleScanner[Reversals].pys # : Download latest version of the Chartboard Extension Classes # (PythonCBEC.pyw) upon which this script is based from # https://www.ivyware.com.au/PythonScripts/PythonCBEC.pyw # : Script interacts with desktop ribbon bar via selected values for # the "Period Units" and "Lookback Periods". # : Requirement is for python 3.8 to be installed # : Based upon Chartboard Extension Classes (CBEC) shipped with # Chartboard product. Script runs as a scanning client of Chartboard. # : Script is run once for each stock encountered by the scanner, # state is not maintained between runs. Selection status MUST # be confirmed for positive scans # : Scanning scripts are allocated the *.pys extension, advisor scripts # the *.pya extenstion and common scripts the *.pyw extension. # import sys sys.path.insert(0, 'C:\\Program Files\\Chartboard\\PythonScripts') # CBEC directory from PythonCBEC import * import ctypes # An included library with Python install. from datetime import datetime from PYCB import PYCB_return from PYCB import PYCB_error # # Environment variables # NOTES: List of current environment variables suitable for debugging import os #print ( 'Python environment') #for param in os.environ.keys(): # print ( "%20s %s" % (param,os.environ[param]) ) # # STEP 1 - Establish Root from which all other objects are descendants # NOTES: Effectively the Chartboard application itself. This script # is coded to run on CScanOHLCvs type views only. # : The parent window 'CView' refers to collection of tabbed views # in the centre of the application, 'this' refers to current # Chartboard view with focus from which script has been activated. oCRoot = CRoot(); # # STEP 2 - Establish CView # NOTES: CView is the parent of all the tabbed view types. Effectively # the View tab under which this python script is running and # identified by the 'this' tag # : Confirm 'CScanOHLCvs' type view, script only supports such oCView = oCRoot.CViewFactory('this'); if not oCView.IsCScanOHLCvs(): raise PYCB_error ( "Script only supports CSanOHLCvs type CView's, not " + oCView.sType ) # # STEP 3 - Establish the CScanOHLCvs object # NOTES: Must be a scan type View tab for this script to work. Fails for # all other view types. Script may only access single scan tab. # : Scan Period Units controlled by the current Ribbon Bar >> Scan Group # >> Scan Period Units tab selection. Alternatively this value may be # over-ridden via PUnits_Year, Quarter, Month, Week or Day definition # from PythonCBEC.pyw # : Calculations are performed and values persist concurrently for all # Period Units. Hence, state for alternative periods can be compared. oCScanOHLCvs = oCView.CScanFactory(); #oCScanOHLCvs.Setenvar_i('PUnits', PUNITS_Month ) #oCScanOHLCvs.Setenvar_i('LBPeriods', 8 ) oCScanOHLCvs.Refresh() # Refreshes cached values # # STEP 4 - Access the CStackOHLCvs object within oCScanOHLCvs # NOTES: The ScanOHLCvs tab builds a synthetic chart for encountered # stocks containing all charts and overlays referenced as # Prerequisites in this script. # : Chart reference order is respected. Chart can be viewed # through context menu of selected stocks list control in the # ScanView # : Some of the Prerequisites are for demonstration and cosmetic # purposes only. Firstly the chart stack is defined as a list of # prerequisites. oCStackOHLCvs = oCScanOHLCvs.CStackFactory() oCStackOHLCvs.Prerequisites('RSI') oCStackOHLCvs.Prerequisites('OHLCvs') oCStackOHLCvs.Prerequisites('MACD') oCStackOHLCvs.Prerequisites('MSA') oCScanOHLCvs.SetSelected ( 0 ) # Not-selected as default summary # # STEP 5 - Configuration of Charts and Overlays within stack # NOTES: Chart decorations that may or may not be referenced by scan logic # : Secondly the Prerequisite overlays are defined for each chart. if oCStackOHLCvs.ChartExists('RSI'): oChartRSI = oCStackOHLCvs.ChartFactory('RSI') oChartRSI.Prerequisites('RSI') oDSeriesRSI = oChartRSI.DSeriesFactory('RSI') # Overlay Signaline oDSeriesRSI.SetConfig_i('Signaline',1) oDSeriesRSI.SetConfig_i('SignalineSMA',1) if oCStackOHLCvs.ChartExists('OHLCvs'): oChartOHLCvs = oCStackOHLCvs.ChartFactory('OHLCvs') oChartOHLCvs.Prerequisites('Reversals-A') # Overlay Reversals oDSeriesReversalsA = oChartOHLCvs.DSeriesFactory('Reversals-A') oDSeriesReversalsA.SetParam_i('RPMask-BULL',RPMask_BULLs) oDSeriesReversalsA.SetParam_i('RPMask-BEAR',RPMask_BEARs_NONE) if oCStackOHLCvs.ChartExists('MACD'): oChartMACD = oCStackOHLCvs.ChartFactory('MACD') oChartMACD.Prerequisites('MACD') oDSeriesMACD = oChartMACD.DSeriesFactory('MACD') # Overlay Buy-Sell signals oDSeriesMACD.SetConfig_i('SignalBUY',1) oDSeriesMACD.SetConfig_i('SignalSELL',1) if oCStackOHLCvs.ChartExists('MSA'): oChartMSA = oCStackOHLCvs.ChartFactory('MSA') oChartMSA.Prerequisites('MSA') oDSeriesMSA = oChartMSA.DSeriesFactory('MSA') # Overlay Signaline oDSeriesMSA.SetConfig_i('Signaline',1) oDSeriesMSA.SetConfig_i('SignalineSMA',1) # STEP 6 - Position cursor at reference date # NOTES: Reference date is controlled by the Ribbon Bar >> Scan Group # >> Reference Date selection. Alternatively this value may be # over-ridden via '[x] RefDate Today' nPUnits = oCScanOHLCvs.nPUnits dRefDateSet = oCScanOHLCvs.SetCursorPos(oCScanOHLCvs.dRefDATE,nPUnits) nDATEmin = oCScanOHLCvs.GetDSetDATE('DATEmin',nPUnits) nDATEmax = oCScanOHLCvs.GetDSetDATE('DATEmax',nPUnits) nRefDateDiff = P2Helpers.P2PUnits_Diff ( oCScanOHLCvs.dRefDATE, nDATEmin, nPUnits ) if nRefDateDiff <= oCScanOHLCvs.nLBPeriods : print ( 'No data exists within loop back periods=' + str(nRefDateDiff) ) raise PYCB_return print ( '-----------------------' ) dRefDATEset = oCScanOHLCvs.SetCursorPos(oCScanOHLCvs.dRefDATE,nPUnits) nCursorPos = oCScanOHLCvs.GetCursorPos(nPUnits) dDiff = P2Helpers.P2PUnits_Diff ( dRefDATEset, nCursorPos, nPUnits ) ################################################# # # Reversal signals # NOTES: Select only those with nominated signals, then apply environmental logic # : dMACD - Calculated MACD value # nBoS - Buy(true) or Sell(false) state # nBoSage - Age of buy/sell state in lookback periods # nAge - Age of Reversal in scan PUnits while oCStackOHLCvs.ChartExists('OHLCvs'): oChartOHLCvs = oCStackOHLCvs.ChartFactory('OHLCvs') oChartOHLCvs.Prerequisites('Reversals-A') oDSeriesReversalsA = oChartOHLCvs.DSeriesFactory ('Reversals-A') #oCScanOHLCvs.FastForward() oReversalOb = oDSeriesReversalsA.ReversalobFactory(nPUnits,0,'Prev') if ( oReversalOb.IsEmpty() == True): break print ( 'Got oREversalsOb' ) dDATEob = oReversalOb.GetValue_d('DATE') dMACD = oDSeriesMACD.GetValue_d('MACD',nPUnits,0) nBoS = oDSeriesMACD.GetValue_i('BoS',nPUnits,0) nBoSage = oDSeriesMACD.GetValue_i('BoSage',nPUnits,0) nAge = P2Helpers.P2PUnits_Diff ( dRefDATEset, dDATEob, nPUnits ) if ( nAge == None or nAge < 0 or nAge > oCScanOHLCvs.nLBPeriods ): break nReversalType = 0 nReversalType = oReversalOb.GetValue_i('Type') print ( 'Passed age test: Type=' + str(nReversalType) ) if ( (nReversalType&RPType_BULL_ENGULFING) == RPType_BULL_ENGULFING ): oCScanOHLCvs.SetSelected ( True ) if ( (nReversalType&RPType_BULL_HAMMER) == RPType_BULL_HAMMER ): oCScanOHLCvs.SetSelected ( True ) if ( (nReversalType&RPType_BULL_HARAMI) == RPType_BULL_HARAMI ): oCScanOHLCvs.SetSelected ( True ) # Flags this stock/chart as selected if ( oReversalOb.IsEmpty() == False and oReversalOb.GetValue_b('IsBullish') ): sSummary = oReversalOb.GetValue_s('Type') + '(' + str(nAge) + ')' oDSeriesReversalsA.Setenvar_s('Summary',sSummary ) oCScanOHLCvs.SetSelected ( True ) if ( nReversalType ): sComments = 'MACD < 0; MACD buy signal <= ' + str(oCScanOHLCvs.nLBPeriods) + oCScanOHLCvs.sPUnits oCScanOHLCvs.Setenvar_s('Comments', sComments ) raise PYCB_return