# Public and for release, CBEC v3.2.06 Build 4255+ [14th November, 2025] # # Copyright(c) Ivyware Pty Ltd 2024-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 Advisor products # 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 Advisor script that uses MACD indicator to model trades # NOTES: Download latest version from # https://www.ivyware.com.au/PythonScripts/SampleModel[MACD].pya # : 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 can be run over any OHLCvs type chart stack, necessary # charts, indicators and overlays that are absent will be auto # generated, calculated and displayed whilst this script is # active. Such will be cleaned up upon completion, or new script # activation, returning OHLCvs chart stack to its original state. # Refer [Ribbon Bar >> Advisors Tab >> {Cancel}] button # : OHLCvs chart scripts can be run over chart stacks generated and # activated through the Scanning results window. # : Simply drag this script from either "Windows File Explorer" or # "Python Scripts Explorer" and drop over any OHLCvs type chart stack. # It then runs automatically and becomes the default [Ribbon Bar # >> Advisors Tab >> {Run Local}] script. # : Based upon Chartboard Extension Classes (CBEC) shipped with # Chartboard product # : Requirement is for phython 3.8 to be installed. # : Can be enhanced as circumstances dictate. However, it should be # be renamed given each successive Chartboard update over-writes this # file. # ***: Script under development and subject to change without notice*** # import sys sys.path.insert(0, 'C:\\Program Files\\Chartboard\\PythonScripts') # CBEC folder 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 CViewOHLCvs 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(); if oCRoot.CWndType('CView','this') != 'CStackOHLCvs': raise PYCB_error ( "Script only supports CStackOHLCvs views, not " + oCRoot.CWndType('CView','this') ) # # STEP 2 - Establish CView # NOTES: CView is the parent of all the tabbed views. Effectively # the View tab under which this python script is running and # identified by the 'this' tag # : CViews can be of many types (CViewOHLCvs, CViewPFigure, CScanOHLCvs etc) # : Confirm 'CViewOHLCvs' type view, script only supports such oCView = oCRoot.CViewFactory('this'); if not oCView.IsCViewOHLCvs(): raise PYCB_error ( "Script only supports CViewOHLCvs type CView's, not " + oCView.sType ) oCView.SetPUnits(PUNITS_Month) # # STEP 3 - Establish the CViewOHLCvs object # NOTES: Must be a OHLCvs type View tab for this script to work. Fails for # all other view types. Script may only access single Chart tab. # : Chart Period Units controlled by the current Ribbon Bar >> Chart Group # >> Chart 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. oCViewOHLCvs = oCRoot.CViewFactory('this'); if not oCViewOHLCvs.IsCViewOHLCvs(): raise PYCB_error ( "Script only supports OHLCvs views, not " + oCViewOHLCvs.sCViewType ) oCViewOHLCvs.PaintEoD(1) # Activates visual updates oCViewOHLCvs.SetPUnits(PUNITS_Month) # # STEP 4 - Access the CStackOHLCvs object within oCViewOHLCvs # NOTES: The CViewOHLCvs tab can add synthetic charts and overlays as # required via the Prerequisites method called within this script. # : Chart reference order is respected. # : Some of the Prerequisites are for demonstration and cosmetic # purposes only. Firstly the chart stack is defined as a list of # prerequisites. # : Stack type MUST identify as 'CStackOHLCvs' oCStackOHLCvs = oCViewOHLCvs.CStackFactory() if not oCStackOHLCvs.IsOHLCvs(): raise PYCB_error ( "Script only supports OHLCvs stacks, not " + oCStackOHLCvs.sStackType ) print ( 'CStack Period Units:' + oCStackOHLCvs.sPUnits) print ( 'CStack Stock Code:' + oCStackOHLCvs.StockCode()) print ( oCStackOHLCvs ) print ( 'CStack Operative Time=' + str(oCStackOHLCvs.DATE()) ) print ( 'CStack Period Units=' + str(oCStackOHLCvs.nPUnits) ) # # STEP 5.1 - MACD Chart confuration # NOTES: Logically MACD chart needs to exist within the chart stack # If not, it will be created and populated with the necessary # components, such as DSeriesMACD, DSeriesMACDsignal, etc. oCStackOHLCvs.Prerequisites('MACD') if oCStackOHLCvs.ChartExists('MACD'): print ('Testing MACD chart components') oChartMACD = oCStackOHLCvs.ChartFactory('MACD') # # Testing DSeriesMACD print ('Testing MACD DSeries components') oDSeriesMACD = oChartMACD.DSeriesFactory('MACD') print('EMA1='+str(oDSeriesMACD.iEMA1periods)) print('EMA2='+str(oDSeriesMACD.iEMA2periods)) print('Signal='+str(oDSeriesMACD.iSignalperiods)) print('Value-MACD='+str(oDSeriesMACD.GetValue_d("MACD",0,0))) print('Value-Signal='+str(oDSeriesMACD.GetValue_d("MACDsignal",0,0))) # # STEP 5.2 - RSI Chart test (NOT UTILISED) # NOTES: Visuals only, no modelling or trading oCStackOHLCvs.Prerequisites('RSI') if oCStackOHLCvs.ChartExists('RSI'): print ('Testing RSI chart components') oChartRSI = oCStackOHLCvs.ChartFactory('RSI') # # Testing DSeriesRSI oDSeriesRSI = oChartRSI.DSeriesFactory('RSI') print('RSIperiods='+str(oDSeriesRSI.iRSIperiods)) print('OBought='+str(oDSeriesRSI.iOBought)) print('OSold='+str(oDSeriesRSI.iOSold)) print('Value-RSI='+str(oDSeriesRSI.GetValue_d("RSI",0,0))) # Step 5.3 - Trading setup # NOTES:'MyModelling' attachment MUST have been pre-loaded # : Always cleanup previous like for like modelling trades # : View modelled trades through the Chartboard workspace. # Refer chart Markups -> Model Positions for further details. # : Observe modelled positions in Grid bar. Use Model label # context menu to configure displayed trades and summaries if oCStackOHLCvs.ChartExists('MACD') : print('Setup Modelling*************************' ) oModel = oCStackOHLCvs.ModelFactory('MyModelling') oModelTrade = oModel.ModelTradeFactory("Firstest",'MyUniqueTag') oChartMACD = oCStackOHLCvs.ChartFactory('MACD') oModelTrade.CleanupTrades() oModelTrade.MarkupTrades ( oChartMACD, TMARKUP_BUY|TMARKUP_SELL|TMARKUP_SUMMARY ) ################################################# # # Monthly Period Units MACD signals # NOTES: Select those BUY instances whereby nBoSage = 0, and dMACD < 0.0 # Rudimentary without any form of finessing # : dMACD - Calculated MACD value # nBoS - Buy(true) or Sell(false) state # nBoSage - Age of buy/sell state in lookback periods # oCStackOHLCvs.PaintEoD(1) oCStackOHLCvs.Setenvar_i('ModelLimitsEoD',1) # Activates display of Model Limits if oCStackOHLCvs.ChartExists('MACD') : print('Perform Modelling*************************' ) oCStackOHLCvs.Rewind() oDSeriesMACD = oChartMACD.DSeriesFactory ('MACD') #Step through each month for which data exists #NOTES: Chart painting usually suspended to manage flicker oChartMACD.PaintEoD(0) # Suspends visual updates while oCStackOHLCvs.Step(PUNITS_Month,1): dMACD = oDSeriesMACD.GetValue_d('MACD',PUNITS_Month,0) nBoS = oDSeriesMACD.GetValue_i('BoS',PUNITS_Month,0) nBoSage = oDSeriesMACD.GetValue_i('BoSage',PUNITS_Month,0) nDATE = oDSeriesMACD.GetValue_d('DATE',PUNITS_Month,0) dtDATE = oDSeriesMACD.GetValue_dt('DATE',PUNITS_Month,0) #Model buys if ( nBoS is not None and nBoS > 0 and nBoSage is not None and nBoSage == 0 and dMACD is not None and dMACD < 0.0 ): #Uae this command for quantity #oModelTrade.BuyQuantity( oDSeriesMACD.GetValue_d('DATE',PUNITS_Day,0), 1000.0 # , oDSeriesMACD.GetValue_d('Price',PUNITS_Day,0) ) #Use this command for value oModelTrade.BuyValue( oDSeriesMACD.GetValue_d('DATE',PUNITS_Day,0), 2500.0 , oDSeriesMACD.GetValue_d('Price',PUNITS_Day,0) ) #Model status print('Post buy Summary - Quantity='+str(oModelTrade.GetValue_d('Quantity')) ) print('Post buy SUmmary - Value='+str(oModelTrade.GetValue_d('Value')) ) #Model sells if ( nBoS is not None and nBoS < 0 and nBoSage is not None and nBoSage == 0 and dMACD is not None and dMACD > 0.0 ): dQuantity = oModelTrade.GetValue_d('Quantity') #Use this command for quantity if ( dQuantity > 0.0 ): oModelTrade.SellQuantity( oDSeriesMACD.GetValue_d('DATE',PUNITS_Day,0), dQuantity , oDSeriesMACD.GetValue_d('Price',PUNITS_Day,0) ) print('Post sell Summary - Quantity='+str(oModelTrade.GetValue_d('Quantity')) ) print('Post sell SUmmary - Value='+str(oModelTrade.GetValue_d('Value')) )