定量的取引システムのバックテスト--- RQalpha、qstrade研究ノート
Quantitative Trading System Backtesting Rqalpha
A、RQalpha
githubアドレス https://github.com/ricequant/rqalpha
1、test.pyファイルを実行し、「logbook.base」という名前のモジュールを表示しません。
インストールする前にアンインストールを解決します:pipアンインストールログブックpipインストールログブック
2、表示されます:RuntimeError:アカウントと初期資金を設定します。
解決する:
二、ジップライン
githubアドレス https://github.com/quantopian/zipline ジップライン学習教材 http://www.zipline.io/
ジップラインコードはもっと悪いコピーです
3、qstrade
githubアドレス https://github.com/mhallsmoore/qstrader
提案された、一時的な学習qstradeを聞いてください。より少ないコード、迅速。
テスト:
価格設定用のデータCSVが見つからなかったため、ティッカーSPYをサブスクライブできませんでした。
価格設定用のデータCSVが見つからなかったため、ティッカーAGGをサブスクライブできませんでした。
トレースバック(最後の最後の呼び出し):
ファイル 'E:/qstrader-master/examples/monthly_liquidate_rebalance_backtest.py'、行108、
run(config、testing、tickers、filename)
ファイル 'E:/qstrader-master/examples/monthly_liquidate_rebalance_backtest.py'、行94、実行中
ポリシーコードで、以下を後ろに追加します。
import os from munch import munchify os.chdir('E:\qstrader-master') config = munchify({'CSV_DATA_DIR': 'data', 'OUTPUT_DIR': 'out', 'testing': True})
画像の保存を変更する必要があります:
Trading_session.pyファイルの最後の部分である最後から2番目の行self.statistics.plot_results()--------> self.statistics.save()
tearsheet.pyファイルの最後の部分、self.plot_results()----------> self.plot_results(ファイル名)
学習問題の要約:
1、buy_and_hold_backtest.pyファイルの実行中にエラーが発生しました。
ファイル 'E: qstrader-master qstrader price_handler yahoo_daily_csv_bar.py'、68行目、_merge_sort_ticker_data
df = pd.concat(self.tickers_data.values())。sort_index()
ファイル 'D: Anaconda3 lib site-packages pandas core reshape concat.py'、行206、concat
copy = copy)
ファイル 'D: Anaconda3 lib site-packages pandas core reshape concat.py'、239行目、__ init__
ValueError( '連結するオブジェクトがありません')を発生させます
ValueError:連結するオブジェクトがありません
1、self.tickers_dataは何ですか? -> self.csv_dir = csv_dir、csv_dirはどこにありますか? ->
2、位置エラー:backtest = TradingSession(config、strategy、tickers、initial_equity、start_date、end_date、events_queue、title = title)がインスタンス化され、
パラメータは次のとおりです。
config-> TEST == munchify({'CSV_DATA_DIR': 'data'、 'OUTPUT_DIR': 'out'})
ストラテジー->インスタンス化、BuyAndHoldStrategy(ティッカー[0]、events_queue)
ティッカー-> ['SPY']
initial_equity-> 10000
start_date-> datetime.datetime(2000,1,1)
end_date-> datetime.datetime(2014,1,1)
events_queue-> queue.Queue()
タイトル-> ['SPYでのバイアンドホールドの例']
よく見ると、qstrader Trading_session.pyの間違った場所、トレーディング。なぜ/どのようにこの段階に入るのですか?
それでもコードを注意深く見る必要があります。メソッドを開始するには、次の__init __()にself._config_sessionがあります。クラスの初期化中に、関数をバックテストする必要があります。
-> def _config_session(self):-> self.price_handler = YahooDailyCsvBarPriceHandler(self.config.CSV_DATA_DIR、self.events_queue、self.tickers、
start_date = self.start_date、end_date = self.end_date)
'' '要求された各金融商品のcsvファイルを読み取り、開く-高-低-収入-取引量(OHLCV)を読み取り、それらをBarEventsとして提供されたイベントキューにストリーミングするように設計されています' ''
-> self.subscribe_ticker(ティッカー)ティッカーをサブスクライブします->以前にサブスクライブしたself._open_ticker_price_csv(ティッカー)
-> self._merge_sort_ticker_data()マージティッカー
デバッグ後、SPY.csvファイルの読み取り部分にエラーコードが見つかりました。コードは次のように表示されます。
ticker_path = os.path.join(self.csv_dir、 '%s.csv'%ticker)
self.tickers_data [ticker] = pd.io.parser.read_csv(ticker_path、....)、奇妙な、ここで次のステップをデバッグします。ticker_pathはなくなりました。
さらに、問題は以下の例のパス、buy_and_hold_backtest.pyパスであることがわかりました。
import os os.getcwd() Out[7]: 'E:\qstrader-master\examples'
また、ファイルパスは次のとおりです。'E: qstrader-master data '、ticker_path =' data \ SPY.csv '。
そのドキュメントの読み取り位置は次のとおりです。'E: qstrader-master examples data SPY.csv '、すべてのファイルを読み取ることはできません。次のように変更できます。
まず、ファイルを追加できますbuy_and_hold_backtest.py:import os os.chdir( 'E:\ qstrader-master')
次に、buy_and_hold_backtest.pyファイルでPythonコンソールを実行し、examples buy_and_hold_backtest.pyを実行します。
run examplesuy_and_hold_backtest.py Backend Qt5Agg is interactive backend. Turning interactive mode on. ticker: SPY self.tickers: {} ticker_path: dataSPY.csv Running Backtest... --------------------------------- Backtest complete. Sharpe Ratio: 0.25 Max Drawdown: 79.59%
2、デバッグプロセスの背後、循環プロセス:
Trading_session.py 1つのクラスのみ:TradingSession(オブジェクト)
注:__ init__の場合、self._config_session()を実行します。
4つのメソッドがあります:1、_config_session(self):2、_continue_loop_condition(self)3、_run_session(self)4、start_trading(self、testing = False)
Buy_and_hold_backtest.pyで、TradingSessionが最初にインスタンス化され、次にstart_tradingメソッドを実行すると、次のプロセスが実行されます。
self._config_session()---->
self.start_trading()-----> self._run_session()----> self._continue_loop_condition
3、_run_session(self)の操作方法
一方self._continue_loop_condition():
試してください:
event = self.events_queue.get(False)
queue.Emptyを除く:
self.price_handler.stream_next()
そうしないと:
イベントがNoneでない場合:
if(event.type == EventType.TICKまたはevent.type == EventType.BAR):。。。。。
#dir(イベント)-> 6つのプロパティがありますアクションprint_order数量ティッカータイプtypename ---> event.type = EventType.ORDER、elifを入力するための条件を満たしていません
エリフevent.type == EventType.ORDER:
self.execution_handler.execute_order(event)
---->
def _continue_loop_condition(self):
self.session_type == 'backtest'の場合:
self.price_handler.continue_backtestを返します
そうしないと:
datetime.now()を返します 表示:self.price_handler from:qstrader.price_handler.yahoo_daily_csv_bar.YahooDailyCsvBarPriceHandlerオブジェクト debug self.price_handler.continue_backtestがTrueの場合、続行します。 -> self.execution_handler.execute_order(event)差出人:qstrader / execute_handler / ib_simulated.py def execute_order(self、event): event.type == EventType.ORDERの場合: #OrderEventから値を取得する タイムスタンプ=self.price_handler.get_last_timestamp(event.ticker) ティッカー= event.ticker action = event.action 数量= event.quantity #約定価格を取得 もしself.price_handler.istick(): bid、ask = self.price_handler.get_best_bid_ask(ticker) fill_price = event.action == 'BOT'の最初の入札かどうかを尋ねる そうしないと: close_price =self.price_handler.get_last_close(ticker) fill_price = close_price #ダミー取引所を設定し、取引手数料ダミーを計算します:シミュレートされた取引 交換= 'ARCA' 手数料=self.calculate_ib_commission(quantity、fill_price) #FillEventを作成し、イベントキューに配置します fill_event =FillEvent(タイムスタンプ、ティッカー、アクション、数量、交換、fill_price、手数料)#インスタンス化されたクラスFillEvent self.events_queue.put(fill_event) self.complianceがNoneでない場合: self.compliance.record_trade(fill_event) ----> self.price_handlerFrom:qstrader / price_handler / base.py、3つのクラスで構成されています: 1、AbstractPriceHandler(オブジェクト)タイプ2、AbstractTickPriceHandler(AbstractPriceHandler)クラス3、AbstractBarPriceHandler(AbstractPriceHandler)クラス self.price_handler.get_last_timestamp()AbstractPriceHandler(オブジェクト)クラスメソッドであり、 def get_last_timestamp(self、ticker): self.tickersのティッカーの場合: timestamp = self.tickers [ticker] ['timestamp'] タイムスタンプを返す self.price_handler.istick()クラス:AbstractBarPriceHandler(AbstractPriceHandler)メソッド:istick def istick(self): Falseを返す def isbar(self): Trueを返す self.price_handler.get_last_close(self、ticker)クラスのAbstractBarPriceHandler(AbstractPriceHandler)メソッドです def get_last_clost(self、ticker):#ticker: ‘SPY’ self.tickersのティッカーの場合:#self.tickersは:{'SPY':{'close':1454375000、 'adj_close':1058253320、 'timestamp':Timestamp( '2000-01-03 00:00:00') }} close_price = self.tickers [ticker] ['close']#self.tickers [ticker] is 辞書 close_priceを返します #ib_similated.pyでclose_priceを取得します -----> ティッカー=イベント。ティッカーアクション=イベント。アクションイベントから:qstrader.event.OrderEvent位置qstrader / event.py event.pyは次のとおりです。合計7つのカテゴリ、基本クラスのイベント。 列挙型インポート列挙型から EventType = Enum( 'EventType'、 'TICK BAR SIGNAL ORDER FILL SENTIMENT') 1、Event(object):2、TickEvent(Event)3、BarEvent(Event)4、SignalEvent(Event)5、OrderEvent(Event)6、FillEvent(Event)7、SentimentEvent(Event) fill_event = FillEvent(タイムスタンプ、ティッカー、アクション、数量、交換、fill_price、手数料) ドライライブが多く、クラスに入るだけで、プロパティ値が ----> self.calculate_ib_commission(quantity、fill_price)差出人:execution_handler / ib_simulated.py 以下を含むクラス:IBSimulatedExecutionHandler(AbstractExecutionHandler) def __init __(self、events_queue、price_handler、compliance = None): defcalculate_ib_commission(self、quantity、fill_price): コミッション=最小(0.5 * fill_price *数量、最大(1.0,0.005 *数量)) PriceParser.parse(commission)を返します -----> self.compliance.record_trade(fill_event)差出人:qstrader / Compliance / example.pyファイル、1つのクラスのみ from .base import AbstractCompliance from:qstrader / Compliance /base.pyにコンテンツがありません クラス:ExampleCompliance(AbstractCompliance)# トランザクションレコードを保存する 3、プロセスを実行しているビューをデバッグします まず、以前にトランザクションに投資したリストを作成します。 run(config、testing、tickers、filename)----> title / initial_equity / start_date / end_date / events_queue /戦略、ロードストラテジー(MonthlyLiquidateRebalanceStrategy(tickers、events_queue)-----> tickers_invested:{'SPY':False、 'AGG':False}、初期化投資ティッカー、-----> ticker_weights / position_sizer、ロードされたクラスの数position(LiquidateRebalancePositionSizer(ticker_weights))-------> qstrader / position_sizer / rebalance.py ----- position_sizer -----取得したinitial_order -----------> バックテストを確立するbacktest = TradingSession(config、strategy、tickers、initial_equity、start_date、end_date、events_queue、position_sizer = position_sizer、title、 ベンチマーク=ティッカー[0])---------> バックテストの結果を開始= backtest.start_trading(テスト=テスト)-------------> 以前の作業を終了しましたが、現在は測定されており、バックテストがインスタンス化され、メソッドstart_trading呼び出しがインスタンス化されています。 -------> self._config_session()、クラスは初期化中に測定する必要がありますPress、self.price_handler = YahooDailyCsvBarPriceHandler(self.config.CSV_DATA_DIR、self.events_queue、 self.tickers、start_date = self.start_date、end_date = self.end_date)-----> event = self.events_queue.get(False)がイベントキューで取得され、各バーイベント---------> self.strategy.calculate_signals(イベント)、ロード戦略、シグナルの計算-----> self.portfolio_handler.update_portfolio_value()、ポートフォリオ値を更新します、------> self.statistics.update(event.time、self.portfolio_handler)、更新された統計-------> 戻り結果戻り結果 4、考えて、場所の複雑さを理解していない A、event.py、EventType、EventType = Enum( 'EventTye'、 'TICK BAR SIGNAL FILL') TICKBARそれぞれTICKBARイベントデータ、SIGNAL FILLどのような役割ですか?各イベントを処理するのは実行中のようなものですか? Buy_and_hold_backtest.pyデバッグビューの場合、イベントのフローは次のとおりです。 ----> Buy_and_hold_backtest.py関数:calculate_signals(self、event) signal = SignalEvent(self.ticker、 'BOT'、suggested_quantity = self.base_quantity) self.events_queue.put(signal)-----------------------> Trading_session.py self.portfolio_handler.on_signal(event) Portfolio_handler.py関数:on_signal(self、signal_event) #単一のシグナルイベントから注文の初期リストを作成します initial_order = self._create_order_from_signal(signal_event) #最初の注文からの取引数を設定します sized_order = self.position_sizer.size_order(self.portfolio、initial_order) #風角制御全体を再編集するか、注文を削除します order_events = self.risk_manager.refine_orders(self.portfolio、sized_order) #イベントキューに入れられた注文 self._place_orders_onto_queue(order_events) 次に、システムをテストするために単純なバージョンをコピーして戻す方法は? 不要な部分を取り除くためには、各部分の全体的な操作プロセスと機能を理解する必要があります。 1、完全なrisk_managerを削除します 2、ORDERイベント、SIGNALイベントをイベントから直接FILLに削除します ORDERイベントは何もしませんでした、1、order_event ----> fill_event 2、self.compliance.record_trade(fill_event) 3、変更されたself.position_sizer Trading_session.pyファイル(1)、self.position_sizerのtrading_session.pyはやや反復的(2)、直接生成パラメーターが順序、ティック、アクション、数量を必要とするときにシグナルを生成します。 今、問題は何ですか? SIGNALの問題が発生し、1、トランザクションへのシグナルで、トランザクションはすぐにパラメータを生成する必要があります(コードがポリシーテンプレートを記述できるよりも大きい) したがって、portfolio_handler.pyに問題があり、order_events self.position_sizerを生成するときに少しロードすると、削除されました。次のように言います: order_events = self.position_sizer.size_order(self.portfolio、initial_order) on_signalportfolio_handler.pyを必要なパラメータに変更できます。 ここでの問題は、主な戦略の数量の数がゼロであり、負荷position_sizerが数量を変更しないことです。 4、各ファイル関数の最初の分析portfolio.py、postition.py、tearsheet.pyファイル。 Portfolio.pyから2つの引数、price_handlerとcash price_handlerは、portfolio_handler.py、trading_session.pyパラメーター、trading_session.pyのパラメーターです。 self.price_handler = YahooDailyCsvBarPriceHandler(self.config.CSV_DATA_DIR、self.events_quue、self.tickers、start_date = self.start_date、end_date = self.end_date) 転送プロセスパラメータ:buy_and_hold_backtest.py initial_equity ----> Trading_session self.equity = PriceParser.parse(equity)----> Portfolio_handler.py self.initial_cash = initial_cash ----> Portfolio.py self.init_cash = cash Portfolio.pyパラメーター: self.price_handler = price_handler self.init_cash = cash self.equity = cash self.cur_cash = cash self.position = {} self.closed_positions = [] self.realised_pnl = 0 5、部分から1000万を掛けた修正、それはとても奇妙に見えました。 第三に、問題は次のとおりです。別のクラスのオブジェクトのインスタンスとして定義されたTradingSessionクラス属性(self.price_handler self.suggested_order self.position_size self.portfolio_handler self.compliance self.statistics)、例のプロセスのプロパティ、パラメータの入力方法は?なぜ私は書くのですか、他に書かれていませんか? 回答:クラスデータ構造の性質、オブジェクトは引数のインスタンス化であり、それは可能です。その主な役割は次のとおりです。関数とパラメーターは、親オブジェクト内の子オブジェクトを指示します。 オブジェクトインスタンス化パラメータの子を使用して、親グローバル変数パラメータを直接渡すことができます。子オブジェクトインスタンス化パラメータは、次に示すように、インスタンスの別のサブ属性に渡すことができます。self.portfolio_handlerクラスインスタンスPortfolioHandlerオブジェクト(プロパティの1つとして) Trading_session、self.portfolio_handlerTearsheetStatisticsインスタンス化パラメータとプロセスの。 第四に、変更 1、position.pytransact_sharesを書き換える関数 2、(x、2)の周りのprice_parser.py行44の小数点以下2桁で、分割可能を変更することに加えて位置 手数料はib_simulated.py0に設定され、印刷量が非常に多く、中間のバグが見つかりました 解決策:以下に示すように、vnpyデータ調整関数を使用してprice_parser.pyファイルのコピーを作成し、変更を加えます。a、コンプライアンスファイル、record_tradeの表示方法、4つのパラメーターは省略できます。 3、