Ejemplo n.º 1
0
    def generate_trades_for_ticker(self, prices_array: QFDataArray, exposures_tms: pd.Series, ticker: Ticker) \
            -> List[Trade]:

        open_prices_tms = cast_data_array_to_proper_type(
            prices_array.loc[:, ticker, PriceField.Open],
            use_prices_types=True)
        # historical data cropped to the time frame of the backtest (from start date till end date)
        historical_data = pd.concat((exposures_tms, open_prices_tms),
                                    axis=1).loc[self._start_date:]

        prev_exposure = 0.0
        trades_list = []

        trade_start_date = None
        trade_exposure = None
        trade_start_price = None

        for curr_date, row in historical_data.iterrows():
            curr_exposure, curr_price = row.values

            # skipping the nan exposures (the first one is sure to be nan)
            if np.isnan(curr_exposure) or np.isnan(curr_price):
                continue

            out_of_the_market = trade_exposure is None
            if out_of_the_market:
                assert prev_exposure == 0.0

                if curr_exposure != 0.0:
                    trade_start_date = curr_date
                    trade_exposure = curr_exposure
                    trade_start_price = curr_price
            else:
                assert prev_exposure != 0.0

                exposure_change = int(curr_exposure - prev_exposure)
                should_close_position = exposure_change != 0.0

                if should_close_position:
                    trades_list.append(
                        Trade(start_time=trade_start_date,
                              end_time=curr_date,
                              contract=self._tickers_to_contracts[ticker],
                              pnl=(curr_price / trade_start_price - 1) *
                              trade_exposure,
                              commission=0.0,
                              direction=int(trade_exposure)))
                    trade_start_date = None
                    trade_exposure = None
                    trade_start_price = None

                    going_into_opposite_direction = curr_exposure != 0.0
                    if going_into_opposite_direction:
                        trade_start_date = curr_date
                        trade_exposure = curr_exposure
                        trade_start_price = curr_price

            prev_exposure = curr_exposure

        return trades_list
Ejemplo n.º 2
0
    def _record_trade_and_transaction(
            self, prev_position_quantity: int, prev_position_avg_price: float, transaction: Transaction):
        """
        Trade is defined as a transaction that goes in the direction of making your position smaller.
        For example:
           selling part or entire long position is a trade
           buying back part or entire short position is a trade
           buying additional shares of existing long position is NOT a trade
        """
        self.transactions.append(transaction)

        is_a_trade = sign(transaction.quantity) * sign(prev_position_quantity) == -1
        if is_a_trade:
            time = transaction.time
            contract = transaction.contract

            # only the part that goes in the opposite direction is considered as a trade
            quantity = min([abs(transaction.quantity), abs(prev_position_quantity)])
            quantity *= sign(prev_position_quantity)  # sign of the position should be preserved

            entry_price = prev_position_avg_price
            exit_price = transaction.average_price_including_commission()
            trade = Trade(time=time,
                          contract=contract,
                          quantity=quantity,
                          entry_price=entry_price,
                          exit_price=exit_price)
            self.trades.append(trade)
Ejemplo n.º 3
0
def get_data():
    start_date = str_to_date('2017-01-01')
    end_date = str_to_date('2017-12-31')

    number_of_trades = 200
    contract = Contract("Example Comdty", "STK", "SIM EXCHANGE")
    trades = [
        Trade(start_date, end_date, contract, pnl, 0, 1, pnl / 10000)
        for pnl in np.random.normal(0, 200, number_of_trades)
    ]
    return trades, 1, start_date, end_date
Ejemplo n.º 4
0
def get_data():
    start_date = str_to_date('2017-01-01')
    end_date = str_to_date('2017-12-31')

    number_of_trades = 200
    ticker = BloombergTicker("MY_STOCK", SecurityType.STOCK, 1)
    trades = [
        Trade(start_date, end_date, ticker, pnl, 0, 1, pnl / 10000)
        for pnl in np.random.normal(0, 200, number_of_trades)
    ]
    return trades, 1, start_date, end_date
Ejemplo n.º 5
0
def get_data():
    start_date = str_to_date('2017-01-01')
    end_date = str_to_date('2017-12-31')

    number_of_trades = 200
    contract = Contract("Example Comdty", "STK", "SIM EXCHANGE")
    percentage_risk = 0.05
    risk = 10000000 * percentage_risk
    trades = [
        Trade(start_date, end_date, contract, pnl, 0, 1, risk)
        for pnl in np.random.normal(0.01, 0.2, number_of_trades)
    ]
    return trades, 1, start_date, end_date
Ejemplo n.º 6
0
    def create_trades_from_backtest_positions(
        self,
        positions: Union[BacktestPosition, Sequence[BacktestPosition]],
        portfolio_values: Optional[QFSeries] = None
    ) -> Union[Trade, Sequence[Trade]]:
        """
        Generates trades from BacktestPositions.

        Parameters
        ----------
        positions: BacktestPosition, Sequence[BacktestPosition]
            Position or positions that will be used to generated the trades
        portfolio_values: Optional[QFSeries]
            Series containing portfolio values at different point in time. It is optional and if provided, the
            percentage pnl value is set in the Trade.

        Returns
        --------
        Trade, Sequence[Trade]
            Generated Trade (in case of one BacktestPosition) or a sequence of Trades
        """
        positions, got_single_position = convert_to_list(
            positions, BacktestPosition)

        def compute_percentage_pnl(position: BacktestPosition):
            if portfolio_values is not None:
                return position.total_pnl / portfolio_values.asof(
                    position.start_time)
            else:
                return None

        trades = [
            Trade(p.start_time, p.end_time, p.contract(), p.total_pnl,
                  p.total_commission(), p.direction(),
                  compute_percentage_pnl(p)) for p in positions
        ]

        if got_single_position:
            return trades[0]
        else:
            return trades