{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", "\n", "dataM1 = pd.read_csv('DAT_ASCII_EURUSD_M1_2015.csv', sep=';',\n", " names=('Time','Open','High','Low','Close', ''),\n", " index_col='Time', parse_dates=True)\n", "dataM1.index += pd.offsets.Hour(7) #7時間のオフセット" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# dfのデータからtfで指定するタイムフレームの4本足データを作成する関数\n", "def TF_ohlc(df, tf):\n", " x = df.resample(tf).ohlc()\n", " O = x['Open']['open']\n", " H = x['High']['high']\n", " L = x['Low']['low']\n", " C = x['Close']['close']\n", " ret = pd.DataFrame({'Open': O, 'High': H, 'Low': L, 'Close': C},\n", " columns=['Open','High','Low','Close'])\n", " return ret.dropna()\n", "\n", "ohlc = TF_ohlc(dataM1, 'H') #1時間足データの作成" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import indicators as ind #indicators.pyのインポート\n", "FastMA = ind.iMA(ohlc, 8) #短期移動平均\n", "SlowMA = ind.iMA(ohlc, 27) #長期移動平均" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from pandas_highcharts.display import display_charts\n", "df = pd.DataFrame({'Close': ohlc['Close'], 'FastMA': FastMA, 'SlowMA': SlowMA})\n", "display_charts(df, chart_type=\"stock\", title=\"MA cross\", figsize=(640,480), grid=True)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [], "source": [ "#買いエントリーシグナル\n", "BuyEntry = ((FastMA > SlowMA) & (FastMA.shift() <= SlowMA.shift())).values\n", "#売りエントリーシグナル\n", "SellEntry = ((FastMA < SlowMA) & (FastMA.shift() >= SlowMA.shift())).values\n", "#買いエグジットシグナル\n", "BuyExit = SellEntry.copy()\n", "#売りエグジットシグナル\n", "SellExit = BuyEntry.copy()" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from numba import jit\n", "#@jit\n", "def Backtest(ohlc, BuyEntry, SellEntry, BuyExit, SellExit, lots=0.1, spread=2):\n", " Open = ohlc['Open'].values #始値\n", " Point = 0.0001 #1pipの値\n", " if(Open[0] > 50): Point = 0.01 #クロス円の1pipの値\n", " Spread = spread*Point #スプレッド\n", " Lots = lots*100000 #実際の売買量\n", " N = len(ohlc) #FXデータのサイズ\n", " BuyExit[N-2] = SellExit[N-2] = True #最後に強制エグジット\n", " BuyPrice = SellPrice = 0.0 # 売買価格\n", " \n", " LongTrade = np.zeros(N) # 買いトレード情報\n", " ShortTrade = np.zeros(N) # 売りトレード情報\n", " \n", " LongPL = np.zeros(N) # 買いポジションの損益\n", " ShortPL = np.zeros(N) # 売りポジションの損益\n", "\n", " for i in range(1,N):\n", " if BuyEntry[i-1] and BuyPrice == 0: #買いエントリーシグナル\n", " BuyPrice = Open[i]+Spread\n", " LongTrade[i] = BuyPrice #買いポジションオープン\n", " elif BuyExit[i-1] and BuyPrice != 0: #買いエグジットシグナル\n", " ClosePrice = Open[i]\n", " LongTrade[i] = -ClosePrice #買いポジションクローズ\n", " LongPL[i] = (ClosePrice-BuyPrice)*Lots #損益確定\n", " BuyPrice = 0\n", "\n", " if SellEntry[i-1] and SellPrice == 0: #売りエントリーシグナル\n", " SellPrice = Open[i]\n", " ShortTrade[i] = SellPrice #売りポジションオープン\n", " elif SellExit[i-1] and SellPrice != 0: #売りエグジットシグナル\n", " ClosePrice = Open[i]+Spread\n", " ShortTrade[i] = -ClosePrice #売りポジションクローズ\n", " ShortPL[i] = (SellPrice-ClosePrice)*Lots #損益確定\n", " SellPrice = 0\n", "\n", " return pd.DataFrame({'Long':LongTrade, 'Short':ShortTrade}, index=ohlc.index),\\\n", " pd.DataFrame({'Long':LongPL, 'Short':ShortPL}, index=ohlc.index)\n", " \n", "Trade, PL = Backtest(ohlc, BuyEntry, SellEntry, BuyExit, SellExit) " ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "買いトレード数 = 132\n", "勝トレード数 = 53\n", "最大勝トレード = 488.0\n", "平均勝トレード = 72.35\n", "負トレード数 = 79\n", "最大負トレード = -146.1\n", "平均負トレード = -39.51\n", "勝率 = 40.15 %\n", "\n", "売りトレード数 = 132\n", "勝トレード数 = 52\n", "最大勝トレード = 320.7\n", "平均勝トレード = 88.32\n", "負トレード数 = 80\n", "最大負トレード = -233.7\n", "平均負トレード = -34.98\n", "勝率 = 39.39 %\n", "\n", "総トレード数 = 264\n", "勝トレード数 = 105\n", "最大勝トレード = 488.0\n", "平均勝トレード = 80.26\n", "負トレード数 = 159\n", "最大負トレード = -233.7\n", "平均負トレード = -37.23\n", "勝率 = 39.77 %\n", "\n", "総利益 = 8427.1\n", "総損失 = -5920.0\n", "総損益 = 2507.1\n", "プロフィットファクター = 1.42\n", "平均損益 = 9.5\n", "最大ドローダウン = 485.1\n", "リカバリーファクター = 5.17\n" ] } ], "source": [ "def BacktestReport(Trade, PL):\n", " LongPL = PL['Long']\n", " LongTrades = np.count_nonzero(Trade['Long'])//2\n", " LongWinTrades = np.count_nonzero(LongPL.clip_lower(0))\n", " LongLoseTrades = np.count_nonzero(LongPL.clip_upper(0))\n", " print('買いトレード数 =', LongTrades)\n", " print('勝トレード数 =', LongWinTrades)\n", " print('最大勝トレード =', LongPL.max())\n", " print('平均勝トレード =', round(LongPL.clip_lower(0).sum()/LongWinTrades, 2))\n", " print('負トレード数 =', LongLoseTrades)\n", " print('最大負トレード =', LongPL.min())\n", " print('平均負トレード =', round(LongPL.clip_upper(0).sum()/LongLoseTrades, 2))\n", " print('勝率 =', round(LongWinTrades/LongTrades*100, 2), '%\\n')\n", "\n", " ShortPL = PL['Short']\n", " ShortTrades = np.count_nonzero(Trade['Short'])//2\n", " ShortWinTrades = np.count_nonzero(ShortPL.clip_lower(0))\n", " ShortLoseTrades = np.count_nonzero(ShortPL.clip_upper(0))\n", " print('売りトレード数 =', ShortTrades)\n", " print('勝トレード数 =', ShortWinTrades)\n", " print('最大勝トレード =', ShortPL.max())\n", " print('平均勝トレード =', round(ShortPL.clip_lower(0).sum()/ShortWinTrades, 2))\n", " print('負トレード数 =', ShortLoseTrades)\n", " print('最大負トレード =', ShortPL.min())\n", " print('平均負トレード =', round(ShortPL.clip_upper(0).sum()/ShortLoseTrades, 2))\n", " print('勝率 =', round(ShortWinTrades/ShortTrades*100, 2), '%\\n')\n", "\n", " Trades = LongTrades + ShortTrades\n", " WinTrades = LongWinTrades+ShortWinTrades\n", " LoseTrades = LongLoseTrades+ShortLoseTrades\n", " print('総トレード数 =', Trades)\n", " print('勝トレード数 =', WinTrades)\n", " print('最大勝トレード =', max(LongPL.max(), ShortPL.max()))\n", " print('平均勝トレード =', round((LongPL.clip_lower(0).sum()+ShortPL.clip_lower(0).sum())/WinTrades, 2))\n", " print('負トレード数 =', LoseTrades)\n", " print('最大負トレード =', min(LongPL.min(), ShortPL.min()))\n", " print('平均負トレード =', round((LongPL.clip_upper(0).sum()+ShortPL.clip_upper(0).sum())/LoseTrades, 2))\n", " print('勝率 =', round(WinTrades/Trades*100, 2), '%\\n')\n", "\n", " GrossProfit = LongPL.clip_lower(0).sum()+ShortPL.clip_lower(0).sum()\n", " GrossLoss = LongPL.clip_upper(0).sum()+ShortPL.clip_upper(0).sum()\n", " Profit = GrossProfit+GrossLoss\n", " Equity = (LongPL+ShortPL).cumsum()\n", " MDD = (Equity.cummax()-Equity).max()\n", " print('総利益 =', round(GrossProfit, 2))\n", " print('総損失 =', round(GrossLoss, 2))\n", " print('総損益 =', round(Profit, 2))\n", " print('プロフィットファクター =', round(-GrossProfit/GrossLoss, 2))\n", " print('平均損益 =', round(Profit/Trades, 2))\n", " print('最大ドローダウン =', round(MDD, 2))\n", " print('リカバリーファクター =', round(Profit/MDD, 2))\n", " return Equity\n", "Equity = BacktestReport(Trade, PL)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "Initial = 10000 # 初期資産\n", "display_charts(pd.DataFrame({'Equity':Equity+Initial}), chart_type=\"stock\", title=\"資産曲線\", figsize=(640,480), grid=True)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def PositionLine(trade):\n", " PosPeriod = 0 #ポジションの期間\n", " Position = False #ポジションの有無\n", " Line = trade.copy()\n", " for i in range(len(Line)):\n", " if trade[i] > 0: Position = True \n", " elif Position: PosPeriod += 1 # ポジションの期間をカウント\n", " if trade[i] < 0:\n", " if PosPeriod > 0:\n", " Line[i] = -trade[i]\n", " diff = (Line[i]-Line[i-PosPeriod])/PosPeriod\n", " for j in range(i-1, i-PosPeriod, -1):\n", " Line[j] = Line[j+1]-diff # ポジションの期間を補間\n", " PosPeriod = 0\n", " Position = False\n", " if trade[i] == 0 and not Position: Line[i] = 'NaN'\n", " return Line\n", "\n", "df = pd.DataFrame({'Open': ohlc['Open'],\n", " 'Long': PositionLine(Trade['Long'].values),\n", " 'Short': PositionLine(Trade['Short'].values)})\n", "display_charts(df, chart_type=\"stock\", title=\"トレードチャート\", figsize=(640,480), grid=True)" ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python [Root]", "language": "python", "name": "Python [Root]" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.2" } }, "nbformat": 4, "nbformat_minor": 0 }