# Public and for release, CBEC v3.1.06 Build 4255+ [10th 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 the MACD indicator to generate # a list of stocks with MACD buy signals at values less than zero # NOTES: Download latest version from # https://www.ivyware.com.au/SampleScanner[MACD].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 phython 3.8 to be installed # : Based upon Chartboard Extension Classes (CBEC) shipped with # Chartboard product. Script only runs as 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 extension 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 CScanOHLCvs 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('SLOPE') 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') oDSeriesRSI.SetConfig_i('Signaline',1) oDSeriesRSI.SetConfig_i('SignalineSMA',1) if oCStackOHLCvs.ChartExists('MACD'): oChartMACD = oCStackOHLCvs.ChartFactory('MACD') oChartMACD.Prerequisites('MACD') oDSeriesMACD = oChartMACD.DSeriesFactory('MACD') oDSeriesMACD.SetConfig_i('SignalBUY',1) oDSeriesMACD.SetConfig_i('SignalSELL',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' dRefDateSet = oCScanOHLCvs.SetCursorPos(oCScanOHLCvs.dRefDATE,oCScanOHLCvs.nPUnits) nDATEmin = oCScanOHLCvs.GetDSetDATE('DATEmin',oCScanOHLCvs.nPUnits) nDATEmax = oCScanOHLCvs.GetDSetDATE('DATEmax',oCScanOHLCvs.nPUnits) nRefDateDiff = P2Helpers.P2PUnits_Diff ( oCScanOHLCvs.dRefDATE, nDATEmin, oCScanOHLCvs.nPUnits ) if nRefDateDiff <= oCScanOHLCvs.nLBPeriods : print ( 'No data exists within loop back periods=' + str(nRefDateDiff) ) raise PYCB_return dRefDATEset = oCScanOHLCvs.SetCursorPos(oCScanOHLCvs.dRefDATE,oCScanOHLCvs.nPUnits) nCursorPos = oCScanOHLCvs.GetCursorPos(oCScanOHLCvs.nPUnits) ################################################# # STEP 7 - Scan Logic # NOTES: Only select those charts with bullish MACD crossovers < nLBPeriods # : dMACD - Calculated MACD value # nBoS - Buy(true) or Sell(false) state # nBoSage - Age of buy/sell state in lookback periods # if ( oCStackOHLCvs.ChartExists('MACD') and nRefDateDiff >= oCScanOHLCvs.nLBPeriods ): oChartMACD = oCStackOHLCvs.ChartFactory('MACD') oChartMACD.Prerequisites('MACD') oDSeriesMACD = oChartMACD.DSeriesFactory ('MACD') oCScanOHLCvs.SetCursorPos(oCScanOHLCvs.dRefDATE,oCScanOHLCvs.nPUnits) dMACD = oDSeriesMACD.GetValue_d('MACD',oCScanOHLCvs.nPUnits,0) nBoS = oDSeriesMACD.GetValue_i('BoS',oCScanOHLCvs.nPUnits,0) nBoSage = oDSeriesMACD.GetValue_i('BoSage',oCScanOHLCvs.nPUnits,0) print ( 'CScanOHLCvs LBPeriods=' + str(oCScanOHLCvs.nLBPeriods) ) if ( nBoS is not None and nBoS > 0 and nBoSage is not None and nBoSage <= oCScanOHLCvs.nLBPeriods and dMACD is not None and dMACD < 0.0 ): print ( 'Selected==============================' ) oCScanOHLCvs.SetSelected ( True ) # Flags this stock/chart as selected sComments = 'MACD < 0; MACD buy signal <= ' + str(oCScanOHLCvs.nLBPeriods) + oCScanOHLCvs.sPUnits oCScanOHLCvs.Setenvar_s('Comments', sComments )