পান্ডার সাথে পাইথনে এসএন্ডপি 500 এর জন্য পূর্বাভাস কৌশল ব্যাকটেস্টিং

লেখক:ভাল, তৈরিঃ 2019-03-29 14:24:50, আপডেটঃ

Matplotlib, pandas এবং scikit-learn এর মতো পরিপক্ক পাইথন লাইব্রেরিগুলিও বয়লারপ্লেট কোড লেখার বা সুপরিচিত অ্যালগরিদমগুলির নিজস্ব বাস্তবায়ন নিয়ে আসার প্রয়োজনীয়তা হ্রাস করে।

পূর্বাভাসের কৌশল

পূর্বাভাস কৌশল নিজেই একটি মেশিন লার্নিং কৌশল উপর ভিত্তি করে পরিচিত একটি বর্গক্ষেত্রীয় বৈষম্য বিশ্লেষক, যা একটি রৈখিক বৈষম্য বিশ্লেষক সঙ্গে ঘনিষ্ঠভাবে সম্পর্কিত হয়। এই মডেল উভয় আর্থিক সময় সিরিজ পূর্বাভাস নিবন্ধে বিস্তারিতভাবে বর্ণনা করা হয়।

পূর্বাভাসদাতা শেয়ারবাজারের আজকের দিকটি পূর্বাভাস দেওয়ার জন্য পূর্ববর্তী দুটি দৈনিক রিটার্নকে একটি সেট ফ্যাক্টর হিসাবে ব্যবহার করে। যদি দিনের up হওয়ার সম্ভাবনা 50% এর বেশি হয় তবে কৌশলটি এসপিওয়াই ইটিএফের 500 শেয়ার কিনে দেয় এবং দিনের শেষে এটি বিক্রি করে। যদি ডাউন ডে এর সম্ভাবনা 50% এর বেশি হয় তবে কৌশলটি এসপিওয়াই ইটিএফের 500 শেয়ার বিক্রি করে এবং তারপরে বন্ধে আবার কিনে। সুতরাং এটি আমাদের ইনট্রাডে ট্রেডিং কৌশলটির প্রথম উদাহরণ।

মনে রাখবেন যে এটি একটি বিশেষভাবে বাস্তবসম্মত ট্রেডিং কৌশল নয়! আমরা অত্যধিক খোলার অস্থিরতা, ব্রোকারেজ দ্বারা অর্ডার রুটিং এবং ওপেন / ক্লোজের আশেপাশের সম্ভাব্য তরলতা সমস্যাগুলির মতো অনেক কারণের কারণে আমরা কখনই উদ্বোধনী বা বন্ধের মূল্য অর্জন করতে পারি না। এছাড়াও আমরা লেনদেনের ব্যয় অন্তর্ভুক্ত করি নি। এটি সম্ভবত রিটার্নের একটি উল্লেখযোগ্য শতাংশ হবে কারণ প্রতিদিন একটি ওভার-ট্রিপ ট্রেড করা হয়। সুতরাং আমাদের পূর্বাভাসদাতার দৈনিক রিটার্নের পূর্বাভাসে তুলনামূলকভাবে সঠিক হওয়া দরকার, অন্যথায় লেনদেনের ব্যয় আমাদের সমস্ত ট্রেডিং রিটার্ন খাবে।

বাস্তবায়ন

অন্যান্য পাইথন / পান্ডা সম্পর্কিত টিউটোরিয়ালগুলির মতো আমি নিম্নলিখিত লাইব্রেরিগুলি ব্যবহার করেছিঃ

  • পাইথন - ২.৭.৩
  • NumPy - 1.8.0
  • পান্ডা - 0.12.0
  • matplotlib - 1.1.0
  • স্কিত-লার্নিং - 0.14.1

snp_forecast.py এর বাস্তবায়নের জন্য নিচের প্রয়োজনbacktest.pyএই পূর্ববর্তী টিউটোরিয়াল থেকে. এছাড়াওforecast.py(যা প্রধানত ফাংশন create_lagged_series ধারণ করে) এই পূর্ববর্তী টিউটোরিয়াল থেকে তৈরি করা হয়. প্রথম ধাপ প্রয়োজনীয় মডিউল এবং বস্তু আমদানি করা হয়ঃ

# snp_forecast.py

import datetime
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import sklearn

from pandas.io.data import DataReader
from sklearn.qda import QDA

from backtest import Strategy, Portfolio
from forecast import create_lagged_series

একবার সমস্ত প্রাসঙ্গিক লাইব্রেরি এবং মডিউলগুলি অন্তর্ভুক্ত হয়ে গেলে এটি কৌশল বিমূর্ত বেস ক্লাসকে উপবিভাগ করার সময়, যেমনটি আমরা পূর্ববর্তী টিউটোরিয়ালগুলিতে করেছি। এসএনপিফোরক্যাস্টিংস্ট্র্যাটেজি একটি স্কোয়ারিক ডিস্ক্রিমিন্যান্ট বিশ্লেষককে এসএন্ডপি 500 স্টক সূচকের ভবিষ্যতের মূল্য পূর্বাভাসের উপায় হিসাবে ফিট করার জন্য ডিজাইন করা হয়েছে। মডেলটির ফিটিং নিচের ফিট_মডেল পদ্ধতিতে সম্পন্ন হয়, যখন প্রকৃত সংকেতগুলি জেনারেট_সিগন্যালস পদ্ধতি থেকে উত্পন্ন হয়। এটি একটি কৌশল শ্রেণীর ইন্টারফেসের সাথে মেলে।

একটি বর্গক্ষেত্রীয় বৈষম্য বিশ্লেষক কীভাবে কাজ করে তার বিবরণ, পাশাপাশি নীচে পাইথন বাস্তবায়ন, আর্থিক সময় সিরিজের পূর্বাভাস সম্পর্কিত পূর্ববর্তী নিবন্ধে বিস্তারিতভাবে বর্ণনা করা হয়েছে। নীচের উত্স কোডের মন্তব্যগুলি প্রোগ্রামটি কী করছে তা ব্যাপকভাবে আলোচনা করেঃ

# snp_forecast.py

class SNPForecastingStrategy(Strategy):
    """    
    Requires:
    symbol - A stock symbol on which to form a strategy on.
    bars - A DataFrame of bars for the above symbol."""

    def __init__(self, symbol, bars):
        self.symbol = symbol
        self.bars = bars
        self.create_periods()
        self.fit_model()

    def create_periods(self):
        """Create training/test periods."""
        self.start_train = datetime.datetime(2001,1,10)
        self.start_test = datetime.datetime(2005,1,1)
        self.end_period = datetime.datetime(2005,12,31)

    def fit_model(self):
        """Fits a Quadratic Discriminant Analyser to the
        US stock market index (^GPSC in Yahoo)."""
        # Create a lagged series of the S&P500 US stock market index
        snpret = create_lagged_series(self.symbol, self.start_train, 
                                      self.end_period, lags=5) 

        # Use the prior two days of returns as 
        # predictor values, with direction as the response
        X = snpret[["Lag1","Lag2"]]
        y = snpret["Direction"]

        # Create training and test sets
        X_train = X[X.index < self.start_test]
        y_train = y[y.index < self.start_test]

        # Create the predicting factors for use 
        # in direction forecasting
        self.predictors = X[X.index >= self.start_test]

        # Create the Quadratic Discriminant Analysis model
        # and the forecasting strategy
        self.model = QDA()
        self.model.fit(X_train, y_train)

    def generate_signals(self):
        """Returns the DataFrame of symbols containing the signals
        to go long, short or hold (1, -1 or 0)."""
        signals = pd.DataFrame(index=self.bars.index)
        signals['signal'] = 0.0       

        # Predict the subsequent period with the QDA model
        signals['signal'] = self.model.predict(self.predictors)

        # Remove the first five signal entries to eliminate
        # NaN issues with the signals DataFrame
        signals['signal'][0:5] = 0.0
        signals['positions'] = signals['signal'].diff() 

        return signals

এখন যেহেতু পূর্বাভাস ইঞ্জিনটি সংকেতগুলি তৈরি করেছে, আমরা একটি মার্কেট ইনট্রাডে পোর্টফোলিও তৈরি করতে পারি। এই পোর্টফোলিও অবজেক্টটি মুভিং এভারেজ ক্রসওভার ব্যাকটেস্ট নিবন্ধে প্রদত্ত উদাহরণ থেকে পৃথক, কারণ এটি ইনট্রাডে ভিত্তিতে ট্রেডিং সম্পাদন করে।

পোর্টফোলিওটি যদি সংকেতটি বলে যে একটি আপ-ডে ঘটবে এবং তারপরে বন্ধের সময়ে বিক্রয় করবে তবে উদ্বোধনী মূল্যে এসপিওয়াইয়ের 500 টি শেয়ার লং (ক্রয়) করার জন্য ডিজাইন করা হয়েছে। বিপরীতভাবে, পোর্টফোলিওটি যদি সংকেতটি বলে যে একটি ডাউন-ডে ঘটবে তবে এসপিওয়াইয়ের 500 টি শেয়ার লং (বিক্রয়) করার জন্য ডিজাইন করা হয়েছে এবং পরবর্তীকালে বন্ধের মূল্যে বন্ধ হবে।

এটি অর্জনের জন্য, বাজারের খোলা এবং বাজারের বন্ধের দামের মধ্যে মূল্যের পার্থক্য প্রতিদিন নির্ধারিত হয়, যার ফলে 500 শেয়ার কেনা বা বিক্রি করা দৈনিক মুনাফা গণনা করা হয়। এটি স্বাভাবিকভাবেই প্রতিটি দিনের মুনাফা / ক্ষতির সমষ্টি যোগ করে একটি ইক্যুইটি বক্ররেখার দিকে পরিচালিত করে। এটি আমাদের প্রতিটি দিনের মুনাফা / ক্ষতির পরিসংখ্যান গণনা করার সুবিধা দেয়।

এখানে MarketIntradayPortfolio এর তালিকা দেওয়া হল:

# snp_forecast.py

class MarketIntradayPortfolio(Portfolio):
    """Buys or sells 500 shares of an asset at the opening price of
    every bar, depending upon the direction of the forecast, closing 
    out the trade at the close of the bar.

    Requires:
    symbol - A stock symbol which forms the basis of the portfolio.
    bars - A DataFrame of bars for a symbol set.
    signals - A pandas DataFrame of signals (1, 0, -1) for each symbol.
    initial_capital - The amount in cash at the start of the portfolio."""

    def __init__(self, symbol, bars, signals, initial_capital=100000.0):
        self.symbol = symbol        
        self.bars = bars
        self.signals = signals
        self.initial_capital = float(initial_capital)
        self.positions = self.generate_positions()
        
    def generate_positions(self):
        """Generate the positions DataFrame, based on the signals
        provided by the 'signals' DataFrame."""
        positions = pd.DataFrame(index=self.signals.index).fillna(0.0)

        # Long or short 500 shares of SPY based on 
        # directional signal every day
        positions[self.symbol] = 500*self.signals['signal']
        return positions
                    
    def backtest_portfolio(self):
        """Backtest the portfolio and return a DataFrame containing
        the equity curve and the percentage returns."""

        # Set the portfolio object to have the same time period
        # as the positions DataFrame
        portfolio = pd.DataFrame(index=self.positions.index)
        pos_diff = self.positions.diff()

        # Work out the intraday profit of the difference
        # in open and closing prices and then determine
        # the daily profit by longing if an up day is predicted
        # and shorting if a down day is predicted        
        portfolio['price_diff'] = self.bars['Close']-self.bars['Open']
        portfolio['price_diff'][0:5] = 0.0
        portfolio['profit'] = self.positions[self.symbol] * portfolio['price_diff']

        # Generate the equity curve and percentage returns
        portfolio['total'] = self.initial_capital + portfolio['profit'].cumsum()
        portfolio['returns'] = portfolio['total'].pct_change()
        return portfolio

চূড়ান্ত ধাপ হল কৌশল এবং পোর্টফোলিওর উদ্দেশ্যগুলিকে একত্রিত করাপ্রধানফাংশন. ফাংশনটি এসপিওয়াই যন্ত্রের জন্য ডেটা অর্জন করে এবং তারপরে এসএন্ডপি 500 সূচকের উপর সিগন্যাল উত্পাদন কৌশল তৈরি করে। এটি ^ জিএসপিসি টিকার দ্বারা সরবরাহ করা হয়। তারপরে 100,000 মার্কিন ডলারের প্রাথমিক মূলধন সহ একটি মার্কেট ইন্ট্রাডে পোর্টফোলিও তৈরি করা হয় (পূর্ববর্তী টিউটোরিয়ালগুলির মতো) । অবশেষে, রিটার্ন গণনা করা হয় এবং ইক্যুইটি বক্ররেখা প্লট করা হয়।

লক্ষ্য করুন যে এই পর্যায়ে কতটা কম কোড প্রয়োজন কারণ সমস্ত ভারী গণনা কৌশল এবং পোর্টফোলিও উপশ্রেণীতে পরিচালিত হয়। এটি নতুন ট্রেডিং কৌশল তৈরি এবং কৌশল পাইপলাইনে ব্যবহারের জন্য দ্রুত তাদের পরীক্ষা করা অত্যন্ত সহজ করে তোলে।

if __name__ == "__main__":
    start_test = datetime.datetime(2005,1,1)
    end_period = datetime.datetime(2005,12,31)

    # Obtain the bars for SPY ETF which tracks the S&P500 index    
    bars = DataReader("SPY", "yahoo", start_test, end_period)
    
    # Create the S&P500 forecasting strategy
    snpf = SNPForecastingStrategy("^GSPC", bars)
    signals = snpf.generate_signals()

    # Create the portfolio based on the forecaster
    portfolio = MarketIntradayPortfolio("SPY", bars, signals,              
                                        initial_capital=100000.0)
    returns = portfolio.backtest_portfolio()

    # Plot results
    fig = plt.figure()
    fig.patch.set_facecolor('white')

    # Plot the price of the SPY ETF
    ax1 = fig.add_subplot(211,  ylabel='SPY ETF price in $')
    bars['Close'].plot(ax=ax1, color='r', lw=2.)

    # Plot the equity curve
    ax2 = fig.add_subplot(212, ylabel='Portfolio value in $')
    returns['total'].plot(ax=ax2, lw=2.)

    fig.show()

প্রোগ্রামের আউটপুট নীচে দেওয়া হয়েছে। এই সময়ের মধ্যে স্টক মার্কেট 4% ফিরে আসে (সম্পূর্ণ বিনিয়োগকৃত কিনুন এবং ধরে রাখার কৌশল অনুমান করে), যখন অ্যালগরিদম নিজেই 4% ফিরে আসে। নোট করুন যে লেনদেনের খরচ (যেমন কমিশন ফি) এই ব্যাকটেস্টিং সিস্টেমে যোগ করা হয়নি। যেহেতু কৌশলটি প্রতিদিন একবার একটি ওভার-ট্রিপ ট্রেড সম্পাদন করে, এই ফিগুলি আয়কে উল্লেখযোগ্যভাবে হ্রাস করার সম্ভাবনা রয়েছে।

২০০৫-০১-০১ থেকে ২০০৬-১২-৩১ পর্যন্ত S&P500 পূর্বাভাস কৌশল কর্মক্ষমতা

পরবর্তী নিবন্ধে আমরা বাস্তবসম্মত লেনদেনের খরচ যোগ করব, অতিরিক্ত পূর্বাভাস ইঞ্জিন ব্যবহার করব, পারফরম্যান্স মেট্রিক নির্ধারণ করব এবং পোর্টফোলিও অপ্টিমাইজেশান সরঞ্জাম সরবরাহ করব।


আরো