示例#1
0
    def __init__(self, ticker, start_date, start_value, strategy):
        """Initialize for a certain ticker and start value.
        - Ticker is a Yahoo ticker.
        - Start value is assumed to be in the same currency as the underlying
        ticker.
        - Strategy should be a subclass of Strategy.
        Note: this involves a HTTP call to Yahoo, so you need an internet
        connection.
        """
        self._strategy = strategy
        if not isinstance(strategy, AbstractStrategy):
            raise Exception("strategy argument should be a subclass of "
                            "AbstractStrategy class.")

        self._state = State(ticker, start_date, start_value)
示例#2
0
class StockMarketStrategySim:
    _strategy = None
    _state = None
    _silent = False

    def __init__(self, ticker, start_date, start_value, strategy):
        """Initialize for a certain ticker and start value.
        - Ticker is a Yahoo ticker.
        - Start value is assumed to be in the same currency as the underlying
        ticker.
        - Strategy should be a subclass of Strategy.
        Note: this involves a HTTP call to Yahoo, so you need an internet
        connection.
        """
        self._strategy = strategy
        if not isinstance(strategy, AbstractStrategy):
            raise Exception("strategy argument should be a subclass of "
                            "AbstractStrategy class.")

        self._state = State(ticker, start_date, start_value)

    def set_silent(self):
        self._silent = True
        return self

    def get_current_value(self):
        """Get the current value."""
        return self._state.get_current_value()

    def run(self):
        """Run the simulation from the given startdate until latest available
        date in data.
        """
        state = self._state

        state.reset()
        while True:
            df_today = state.get_df_for_current_date()
            self._evaluate_day(df_today)
            if not state.increment_current_date():
                self._log((
                    "Done! Reached date {}. Total trades: {}. "
                    "Total transactioncosts: {:0.2f}.")
                    .format(state.get_current_date(), state.get_num_trades(),
                            state.get_total_transactioncosts()))
                break

        if not self._silent:
            plot = Plot()
            plot.plot_results(state, self._strategy.__class__.__name__)

    def _evaluate_day(self, df_day):
        """Process actions for a single day and update the portfolio value."""
        open = df_day['Open'][0]
        close = df_day['Close'][0]
        prev_close = df_day['PrevClose'][0]
        avg = (open + close) / 2.0
        ticker_proc_change = (close - prev_close) / prev_close

        prevclose_value = self._state.get_current_value()

        if self._state.position_is_long():
            if self._strategy.sell_trigger(self._state):
                # Selling at halfway point today.
                # Add perc. diff from Open to avg and sell.
                self._state.apply_percentual_change((1 + (avg - open) / open))
                self._sell()
            else:
                # Had a full day exposure to the market.
                # Add perc. diff from Open to Close
                self._state.apply_percentual_change(1 + ticker_proc_change)
        else:
            # Position is not long, so it's cash
            if self._strategy.buy_trigger(self._state):
                self._buy()
                # Buying at halfway point today.
                # Add perc. diff from avg to Close
                self._state.apply_percentual_change((1 + (close - avg) / avg))

        self._state.save_value_in_df()
        self._strategy.update(self._state)

        value_proc_change = (self._state.get_current_value() -
                             prevclose_value) / prevclose_value

        self._log((
            "{}. Your value at Close: {:8.2f} ({:5.2f} %). "
            "Ticker at Close: {:8.2f} "
            "({:5.2f} %). {}")
            .format(df_day.index[0].date(), self._state.get_current_value(),
                    value_proc_change * 100, close, ticker_proc_change * 100,
                    self._strategy.status_update_suffix()))

    def _buy(self):
        """Perform a buy action using all available cash."""
        tc = self._get_transaction_cost(self._state.get_current_value())
        self._state.set_long_position()
        self._log("Bought long position for {0} (transaction cost: {1})"
                  .format(self._state.get_current_value(), tc))
        self._state.apply_transaction_cost(tc)

    def _sell(self):
        """Sell everything."""
        tc = self._get_transaction_cost(self._state.get_current_value())
        self._state.set_cash_position()
        self._log("Sold long position for {0} (transaction cost: {1})"
                  .format(self._state.get_current_value(), tc))
        self._state.apply_transaction_cost(tc)

    def _get_transaction_cost(self, amount):
        """Return transaction costs for a given amount. This is for a Dutch
        bank (in euro).
        """
        return min(max(amount * 0.001 + 6.50, 10.0), 150.0)

    def _log(self, s):
        if not self._silent:
            print(s)