├── README.md ├── presentations └── Presentation - Algorithmic Trading with Python.pdf ├── .gitignore └── strategies └── sma_crossover ├── trading_strategy.py └── backtest.ipynb /README.md: -------------------------------------------------------------------------------- 1 | # algo-trading-strategies 2 | Algorithmic Trading Startegies with Python and MetaTrader5 3 | -------------------------------------------------------------------------------- /presentations/Presentation - Algorithmic Trading with Python.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/traderpy/algo-trading-strategies/HEAD/presentations/Presentation - Algorithmic Trading with Python.pdf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | /strategies/sma_crossover/account_credentials.py 131 | /live_trading/sma_crossover/ 132 | /live_trading/ 133 | -------------------------------------------------------------------------------- /strategies/sma_crossover/trading_strategy.py: -------------------------------------------------------------------------------- 1 | import MetaTrader5 as mt5 2 | import pandas as pd 3 | import time 4 | from datetime import datetime 5 | from account_credentials import LOGIN, PASSWORD, SERVER 6 | 7 | symbol = 'DE40' 8 | timeframe = mt5.TIMEFRAME_M5 9 | volume = 0.5 10 | strategy_name = 'ma_trendfollowing' 11 | 12 | 13 | def get_sma(symbol, timeframe, period): 14 | sma = pd.DataFrame(mt5.copy_rates_from_pos(symbol, timeframe, 1, period))['close'].mean() 15 | 16 | return sma 17 | 18 | 19 | def close_position(position, deviation=20, magic=12345): 20 | 21 | order_type_dict = { 22 | 0: mt5.ORDER_TYPE_SELL, 23 | 1: mt5.ORDER_TYPE_BUY 24 | } 25 | 26 | price_dict = { 27 | 0: mt5.symbol_info_tick(symbol).bid, 28 | 1: mt5.symbol_info_tick(symbol).ask 29 | } 30 | 31 | request = { 32 | "action": mt5.TRADE_ACTION_DEAL, 33 | "position": position['ticket'], # select the position you want to close 34 | "symbol": symbol, 35 | "volume": volume, # FLOAT 36 | "type": order_type_dict[position['type']], 37 | "price": price_dict[position['type']], 38 | "deviation": deviation, # INTERGER 39 | "magic": magic, # INTERGER 40 | "comment": strategy_name, 41 | "type_time": mt5.ORDER_TIME_GTC, 42 | "type_filling": mt5.ORDER_FILLING_IOC, 43 | } 44 | 45 | order_result = mt5.order_send(request) 46 | return(order_result) 47 | 48 | 49 | def close_positions(order_type): 50 | order_type_dict = { 51 | 'buy': 0, 52 | 'sell': 1 53 | } 54 | 55 | if mt5.positions_total() > 0: 56 | positions = mt5.positions_get() 57 | 58 | positions_df = pd.DataFrame(positions, columns=positions[0]._asdict().keys()) 59 | 60 | if order_type != 'all': 61 | positions_df = positions_df[(positions_df['type'] == order_type_dict[order_type])] 62 | 63 | for i, position in positions_df.iterrows(): 64 | order_result = close_position(position) 65 | 66 | print('order_result: ', order_result) 67 | 68 | 69 | def check_allowed_trading_hours(): 70 | if 9 < datetime.now().hour < 17: 71 | return True 72 | else: 73 | return False 74 | 75 | 76 | def market_order(symbol, volume, order_type, deviation=20, magic=12345): 77 | 78 | order_type_dict = { 79 | 'buy': mt5.ORDER_TYPE_BUY, 80 | 'sell': mt5.ORDER_TYPE_SELL 81 | } 82 | 83 | price_dict = { 84 | 'buy': mt5.symbol_info_tick(symbol).ask, 85 | 'sell': mt5.symbol_info_tick(symbol).bid 86 | } 87 | 88 | request = { 89 | "action": mt5.TRADE_ACTION_DEAL, 90 | "symbol": symbol, 91 | "volume": volume, # FLOAT 92 | "type": order_type_dict[order_type], 93 | "price": price_dict[order_type], 94 | "sl": 0.0, # FLOAT 95 | "tp": 0.0, # FLOAT 96 | "deviation": deviation, # INTERGER 97 | "magic": magic, # INTERGER 98 | "comment": strategy_name, 99 | "type_time": mt5.ORDER_TIME_GTC, 100 | "type_filling": mt5.ORDER_FILLING_IOC, 101 | } 102 | 103 | order_result = mt5.order_send(request) 104 | return(order_result) 105 | 106 | 107 | if __name__ == '__main__': 108 | is_initialized = mt5.initialize() 109 | print('initialize: ', is_initialized) 110 | 111 | is_logged_in = mt5.login(LOGIN, PASSWORD, SERVER) 112 | print('logged in: ', is_logged_in) 113 | print('\n') 114 | 115 | while True: 116 | account_info = mt5.account_info() 117 | print(datetime.now(), 118 | '| Login: ', account_info.login, 119 | '| Balance: ', account_info.balance, 120 | '| Equity: ' , account_info.equity) 121 | 122 | num_positions = mt5.positions_total() 123 | 124 | if not check_allowed_trading_hours(): 125 | close_positions('all') 126 | 127 | fast_sma = get_sma(symbol, timeframe, 10) 128 | slow_sma = get_sma(symbol, timeframe, 100) 129 | 130 | if fast_sma > slow_sma: 131 | close_positions('sell') 132 | 133 | if num_positions == 0 and check_allowed_trading_hours(): 134 | order_result = market_order(symbol, volume, 'buy') 135 | print(order_result) 136 | 137 | elif fast_sma < slow_sma: 138 | close_positions('buy') 139 | 140 | if num_positions == 0 and check_allowed_trading_hours(): 141 | order_result = market_order(symbol, volume, 'sell') 142 | print(order_result) 143 | 144 | time.sleep(1) 145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /strategies/sma_crossover/backtest.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 5, 6 | "metadata": { 7 | "collapsed": true, 8 | "pycharm": { 9 | "name": "#%%\n" 10 | } 11 | }, 12 | "outputs": [], 13 | "source": [ 14 | "import pandas as pd\n", 15 | "import plotly.express as px\n", 16 | "import MetaTrader5 as mt5\n", 17 | "\n", 18 | "from account_credentials import LOGIN, PASSWORD, SERVER\n", 19 | "from datetime import datetime" 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": 6, 25 | "outputs": [ 26 | { 27 | "data": { 28 | "text/plain": "True" 29 | }, 30 | "execution_count": 6, 31 | "metadata": {}, 32 | "output_type": "execute_result" 33 | } 34 | ], 35 | "source": [ 36 | "mt5.initialize()\n", 37 | "mt5.login(LOGIN, PASSWORD, SERVER)" 38 | ], 39 | "metadata": { 40 | "collapsed": false, 41 | "pycharm": { 42 | "name": "#%%\n" 43 | } 44 | } 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": 13, 49 | "outputs": [], 50 | "source": [ 51 | "symbol = 'DE40'\n", 52 | "timeframe = mt5.TIMEFRAME_M5\n", 53 | "start_date = datetime(2022, 1, 1)\n", 54 | "end_date = datetime(2022, 7, 1)\n", 55 | "trade_volume = 0.5\n", 56 | "commission = 1" 57 | ], 58 | "metadata": { 59 | "collapsed": false, 60 | "pycharm": { 61 | "name": "#%%\n" 62 | } 63 | } 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": 14, 68 | "outputs": [ 69 | { 70 | "ename": "KeyError", 71 | "evalue": "'time'", 72 | "output_type": "error", 73 | "traceback": [ 74 | "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m", 75 | "\u001B[1;31mKeyError\u001B[0m Traceback (most recent call last)", 76 | "\u001B[1;32mc:\\users\\juicy\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\pandas\\core\\indexes\\base.py\u001B[0m in \u001B[0;36mget_loc\u001B[1;34m(self, key, method, tolerance)\u001B[0m\n\u001B[0;32m 3360\u001B[0m \u001B[1;32mtry\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m-> 3361\u001B[1;33m \u001B[1;32mreturn\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_engine\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mget_loc\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mcasted_key\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 3362\u001B[0m \u001B[1;32mexcept\u001B[0m \u001B[0mKeyError\u001B[0m \u001B[1;32mas\u001B[0m \u001B[0merr\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", 77 | "\u001B[1;32mc:\\users\\juicy\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\pandas\\_libs\\index.pyx\u001B[0m in \u001B[0;36mpandas._libs.index.IndexEngine.get_loc\u001B[1;34m()\u001B[0m\n", 78 | "\u001B[1;32mc:\\users\\juicy\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\pandas\\_libs\\index.pyx\u001B[0m in \u001B[0;36mpandas._libs.index.IndexEngine.get_loc\u001B[1;34m()\u001B[0m\n", 79 | "\u001B[1;32mpandas\\_libs\\hashtable_class_helper.pxi\u001B[0m in \u001B[0;36mpandas._libs.hashtable.PyObjectHashTable.get_item\u001B[1;34m()\u001B[0m\n", 80 | "\u001B[1;32mpandas\\_libs\\hashtable_class_helper.pxi\u001B[0m in \u001B[0;36mpandas._libs.hashtable.PyObjectHashTable.get_item\u001B[1;34m()\u001B[0m\n", 81 | "\u001B[1;31mKeyError\u001B[0m: 'time'", 82 | "\nThe above exception was the direct cause of the following exception:\n", 83 | "\u001B[1;31mKeyError\u001B[0m Traceback (most recent call last)", 84 | "\u001B[1;32m~\\AppData\\Local\\Temp/ipykernel_16300/294319608.py\u001B[0m in \u001B[0;36m\u001B[1;34m\u001B[0m\n\u001B[0;32m 1\u001B[0m \u001B[0mbars\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mpd\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mDataFrame\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mmt5\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mcopy_rates_range\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0msymbol\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mtimeframe\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mstart_date\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mend_date\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m----> 2\u001B[1;33m \u001B[0mbars\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;34m'time'\u001B[0m\u001B[1;33m]\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mpd\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mto_datetime\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mbars\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;34m'time'\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0munit\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;34m's'\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 3\u001B[0m \u001B[0mbars\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;34m'trade_volume'\u001B[0m\u001B[1;33m]\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mtrade_volume\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 4\u001B[0m \u001B[0mbars\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", 85 | "\u001B[1;32mc:\\users\\juicy\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\pandas\\core\\frame.py\u001B[0m in \u001B[0;36m__getitem__\u001B[1;34m(self, key)\u001B[0m\n\u001B[0;32m 3456\u001B[0m \u001B[1;32mif\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mcolumns\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mnlevels\u001B[0m \u001B[1;33m>\u001B[0m \u001B[1;36m1\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 3457\u001B[0m \u001B[1;32mreturn\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_getitem_multilevel\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mkey\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m-> 3458\u001B[1;33m \u001B[0mindexer\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mcolumns\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mget_loc\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mkey\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 3459\u001B[0m \u001B[1;32mif\u001B[0m \u001B[0mis_integer\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mindexer\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 3460\u001B[0m \u001B[0mindexer\u001B[0m \u001B[1;33m=\u001B[0m \u001B[1;33m[\u001B[0m\u001B[0mindexer\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", 86 | "\u001B[1;32mc:\\users\\juicy\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\pandas\\core\\indexes\\base.py\u001B[0m in \u001B[0;36mget_loc\u001B[1;34m(self, key, method, tolerance)\u001B[0m\n\u001B[0;32m 3361\u001B[0m \u001B[1;32mreturn\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_engine\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mget_loc\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mcasted_key\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 3362\u001B[0m \u001B[1;32mexcept\u001B[0m \u001B[0mKeyError\u001B[0m \u001B[1;32mas\u001B[0m \u001B[0merr\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m-> 3363\u001B[1;33m \u001B[1;32mraise\u001B[0m \u001B[0mKeyError\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mkey\u001B[0m\u001B[1;33m)\u001B[0m \u001B[1;32mfrom\u001B[0m \u001B[0merr\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 3364\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 3365\u001B[0m \u001B[1;32mif\u001B[0m \u001B[0mis_scalar\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mkey\u001B[0m\u001B[1;33m)\u001B[0m \u001B[1;32mand\u001B[0m \u001B[0misna\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mkey\u001B[0m\u001B[1;33m)\u001B[0m \u001B[1;32mand\u001B[0m \u001B[1;32mnot\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mhasnans\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", 87 | "\u001B[1;31mKeyError\u001B[0m: 'time'" 88 | ] 89 | } 90 | ], 91 | "source": [ 92 | "bars = pd.DataFrame(mt5.copy_rates_range(symbol, timeframe, start_date, end_date))\n", 93 | "bars['time'] = pd.to_datetime(bars['time'], unit='s')\n", 94 | "bars['trade_volume'] = trade_volume\n", 95 | "bars" 96 | ], 97 | "metadata": { 98 | "collapsed": false, 99 | "pycharm": { 100 | "name": "#%%\n" 101 | } 102 | } 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": null, 107 | "outputs": [], 108 | "source": [ 109 | "bars['sma_100'] = bars['close'].rolling(100).mean()\n", 110 | "bars['sma_10'] = bars['close'].rolling(10).mean()\n", 111 | "bars['hour'] = bars['time'].dt.hour\n", 112 | "bars" 113 | ], 114 | "metadata": { 115 | "collapsed": false, 116 | "pycharm": { 117 | "name": "#%%\n" 118 | } 119 | } 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": null, 124 | "outputs": [], 125 | "source": [ 126 | "bars2 = bars.dropna().copy()\n", 127 | "\n", 128 | "def get_signal(x):\n", 129 | "\n", 130 | " if 9 <= x['hour'] <= 18:\n", 131 | "\n", 132 | " if x['sma_10'] > x['sma_100']:\n", 133 | " return 1\n", 134 | " elif x['sma_10'] < x['sma_100']:\n", 135 | " return -1\n", 136 | "\n", 137 | " return 0\n", 138 | "\n", 139 | "bars2['signal'] = bars2.apply(get_signal, axis=1)\n", 140 | "bars2['prev_price'] = bars2['close'].shift(1)\n", 141 | "bars2['price_change'] = bars2['close'] - bars2['prev_price']\n", 142 | "\n", 143 | "bars2['signal_change'] = (bars2['signal'] - bars2['signal'].shift(1)).abs()\n", 144 | "bars2['commission'] = bars2.apply(lambda x: commission * x['signal_change'] * x['trade_volume'], axis=1)\n", 145 | "bars2" 146 | ], 147 | "metadata": { 148 | "collapsed": false, 149 | "pycharm": { 150 | "name": "#%%\n" 151 | } 152 | } 153 | }, 154 | { 155 | "cell_type": "code", 156 | "execution_count": null, 157 | "outputs": [], 158 | "source": [ 159 | "bars3 = bars2.dropna().copy()\n", 160 | "bars3['profit'] = bars3['signal'] * bars3['price_change'] * bars3['trade_volume']\n", 161 | "bars3['gross_profit'] = bars3['profit'].cumsum()\n", 162 | "\n", 163 | "bars3['net_profit'] = bars3['gross_profit'] - bars3['commission'].cumsum()\n", 164 | "\n", 165 | "\n", 166 | "bars3" 167 | ], 168 | "metadata": { 169 | "collapsed": false, 170 | "pycharm": { 171 | "name": "#%%\n" 172 | } 173 | } 174 | }, 175 | { 176 | "cell_type": "code", 177 | "execution_count": null, 178 | "outputs": [], 179 | "source": [ 180 | "px.line(bars3, 'time', ['gross_profit', 'net_profit'], title=\"DE40 Backtest MA Trendfollowing\")" 181 | ], 182 | "metadata": { 183 | "collapsed": false, 184 | "pycharm": { 185 | "name": "#%%\n" 186 | } 187 | } 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": null, 192 | "outputs": [], 193 | "source": [], 194 | "metadata": { 195 | "collapsed": false, 196 | "pycharm": { 197 | "name": "#%%\n" 198 | } 199 | } 200 | } 201 | ], 202 | "metadata": { 203 | "kernelspec": { 204 | "display_name": "Python 3", 205 | "language": "python", 206 | "name": "python3" 207 | }, 208 | "language_info": { 209 | "codemirror_mode": { 210 | "name": "ipython", 211 | "version": 2 212 | }, 213 | "file_extension": ".py", 214 | "mimetype": "text/x-python", 215 | "name": "python", 216 | "nbconvert_exporter": "python", 217 | "pygments_lexer": "ipython2", 218 | "version": "2.7.6" 219 | } 220 | }, 221 | "nbformat": 4, 222 | "nbformat_minor": 0 223 | } --------------------------------------------------------------------------------