Hi, I think I've got something. Happy to be sharing it with the community, as I've had many questions of mine answered here, so hopefully finally able to give something back. The answer was the nbformat module I mentioned earlier. The code isn't really plug and play, but should be enough there for someone who understands a little bit of afl and little bit of Python to use it.
Amibroker code here, must be run as a scan using Apply to: *Current on the ~~~EQUITY curve you want to export. I would recommend changing the name of the ~~~EQUITY ticker to something of note, I have used ~Research28 in my example. My plan is to use a unique project (.apx) file and code (.afl) file also called Research28, so I will be able to always have a cross reference between the equity curve I am viewing in my Jupyter Notebook and the AB code and settings that were used to generate it.
PyLoadFromFile( "ExportCurve", "C:\\Sample Code\\ExportCurveSample.py" );
// Make up a parameter where we can enter the notebook name was want the curve inserted into, this must be a notebook that is already created
notebookname = ParamStr( "Notebook Name", StrTrim( Name(), "~", 1 ) );
// Since when backtesting I create my own Composite tickers to store equity curves and preface with a tilda (~), the default name for the note book is just the symbol name less the tilda
path = "C:\\Sample Code\\" + StrTrim( Name(), "~", 1 ) + ".csv";
// Below is the code we use to write the equity curve data to a CSV file.
// By writing it to a CSV file, the data is always there and we can use the Jupyter notebook regarless of whether AB is open
/*
Code for writing a CSV file taken from "Quantitative Technical Analysis" written by Dr. Howard Bandy and published bSample Codey Blue Owl Press, Inc.
Copyright 2014 Howard Bandy
Author: Howard Bandy
Blue Owl Press, Inc.
www.BlueOwlPress.com
*/
// First check if the file exists, as we do not want to overwrite an existing file.
filestatus = fgetstatus( path, 3 );
if ( IsNull(filestatus) )
{
_TRACE("This file does not exist, ok to create it.");
fh = fopen( path, "w" );
if ( fh )
{
fputs( "Ticker,Date,Hr:Min,Open,High,Low,Close,Volume\n",
fh );
nm = Name();
y = Year();
m = Month();
d = Day();
Hr = Hour();
Mn = Minute();
for ( i = 0; i < BarCount; i++ )
{
ns = nm + ",";
fputs( ns, fh );
ds = StrFormat( "%02.0f-%02.0f-%02.0f,",
y[ i ], m[ i ], d[ i ] );
fputs( ds, fh );
ts = StrFormat( "%02.0f:%02.0f,",
hr[ i ], mn[ i ] );
fputs( ts, fh );
qs = StrFormat( "%.4f, %.4f, %.4f, %.4f, %.0f\n",
O[ i ], H[ i ], L[ i ], C[ i ], V[ i ] );
fputs( qs, fh );
}
fclose( fh );
}
}
else
{
_TRACE("File of the same name already exists, please delete file before proceeding.");
}
PyEvalFunction( "ExportCurve", "WriteToJupyter", StrTrim( Name(), "~", 1 ), notebookname );
This also writes the equity curve to a csv file on the hard drive, so that the data is always there and we can use the Jupyter Notebook later independently without having AB open.
Then the python code. Note that the Jupyter notebook must already have been created. For me this isn't an issue because I will have one already created with a heading, aim, introduction, etc, I don't just want a chart at the start of my notebook.
import AmiPy
import nbformat
def WriteToJupyter( csvfilename, notebookname ):
# assume that the Jupyter notebook already exists
notebook = nbformat.read("C:\\Sample Code\\" + notebookname + ".ipynb", as_version=4)
path = "C:\\Sample Code\\" + csvfilename + ".csv"
# These blocks make up the code for the written text
text1 = "This equity curve is taken from the equity curve data in the CSV file: "
text2 = path
text3 = ". To trace back the construction of the equity curve, note that an Amibroker project (apx) and code (afl) file have been named with the same name."
# These blocks make up the code to plot the equity curve
code1 = "import pandas as pd\nimport datetime as dt\nimport matplotlib.pyplot as plt\n%matplotlib inline\ndf = pd.read_csv( '"
code2 = path
code3 = "')\ndf = df.set_index('Date', inplace=False)\ndf.index = pd.to_datetime( df.index )\ndf.drop( columns = ['Ticker', 'Hr:Min' ], inplace=True )\n"
code4 = "df.rename( columns = {'Close': 'Closed Profit', 'Open': 'Open Profit', 'Low': 'Open Trade Count', 'High': 'Capital In Trades', 'Volume': 'Closed Drawdown'}, inplace=True)\n"
code5 = "df['Open Drawdown'] = df['Open Profit'] - df['Open Profit'].cummax()\nfig, (ax1, ax2 ) = plt.subplots(2, 1, gridspec_kw={'height_ratios': [2.5, 1] }, sharex=True, figsize=(20,15) )\n"
code6 = "ax1.plot( df.index, df['Open Profit'], color='green' )\nax2.plot( df.index, df['Open Drawdown'], color='red')\nax1.grid()\nax2.grid()\nplt.show()"
# Make the text and code fragments a list, for entry into nbformat
text = [ text1, text2, text3 ]
code = [ code1, code2, code3, code4, code5, code6 ]
cells = [nbformat.v4.new_markdown_cell(text), nbformat.v4.new_code_cell(code)]
notebook['cells'].extend(cells)
nbformat.write(notebook,'C:\\Sample Code\\' + notebookname + '.ipynb')
Excuse the novice formatting of the code, it's well because I'm a novice. Hopefully this might be useful for someone else like me that loves the power and usability of Amibroker, but has become accustomed to using Jupyter Notebooks to record research.