コード例 #1
0
    def test_slippage_and_commission_dispatching(self):
        blotter = SimulationBlotter(
            self.sim_params,
            equity_slippage=FixedSlippage(spread=0.0),
            future_slippage=FixedSlippage(spread=2.0),
            equity_commission=PerTrade(cost=1.0),
            future_commission=PerTrade(cost=2.0),
        )
        blotter.order(self.asset_24, 1, MarketOrder())
        blotter.order(self.future_cl, 1, MarketOrder())

        bar_data = self.create_bardata(
            simulation_dt_func=lambda: self.sim_params.sessions[-1], )
        txns, commissions, _ = blotter.get_transactions(bar_data)

        # The equity transaction should have the same price as its current
        # price because the slippage spread is zero. Its commission should be
        # $1.00.
        equity_txn = txns[0]
        self.assertEqual(
            equity_txn.price,
            bar_data.current(equity_txn.asset, 'price'),
        )
        self.assertEqual(commissions[0]['cost'], 1.0)

        # The future transaction price should be 1.0 more than its current
        # price because half of the 'future_slippage' spread is added. Its
        # commission should be $2.00.
        future_txn = txns[1]
        self.assertEqual(
            future_txn.price,
            bar_data.current(future_txn.asset, 'price') + 1.0,
        )
        self.assertEqual(commissions[1]['cost'], 2.0)
コード例 #2
0
    def initialize(self,
                   stock_list,
                   PCA_Weight,
                   R_PCA_Protfolio,
                   window_length=60):
        self.K_factors = 5
        self.spreads = []
        self.invested = 0
        self.window_length = window_length
        self.ols_transform = ols_transform(refresh_period=1,
                                           window_length=self.window_length)
        self.regressor_name = stock_list
        self.instant_fill = True
        self.slippage = FixedSlippage(spread=0)
        self.sscore = [
        ]  # store those sscores which can be regarded as the hist

        self.beta = []  # keep track of the changing beta
        self.before_sid1_position = []  # keep track of the sid1 position
        self.before_sid2_position = []  # keep track of the sid2 position

        self.current_sid1_price = []
        self.current_sid2_price = []

        self.PCA_Weight = PCA_Weight
        self.PCA_R_PCA_Protfolio = R_PCA_Protfolio[:, 0:self.
                                                   K_factors]  ##############################
コード例 #3
0
    def test_blotter_processes_splits(self):
        blotter = SimulationBlotter(equity_slippage=FixedSlippage())

        # set up two open limit orders with very low limit prices,
        # one for sid 1 and one for sid 2
        asset1 = self.asset_finder.retrieve_asset(1)
        asset2 = self.asset_finder.retrieve_asset(2)
        asset133 = self.asset_finder.retrieve_asset(133)

        blotter.order(asset1, 100, LimitOrder(10, asset=asset1))
        blotter.order(asset2, 100, LimitOrder(10, asset=asset2))

        # send in splits for assets 133 and 2.  We have no open orders for
        # asset 133 so it should be ignored.
        blotter.process_splits([(asset133, 0.5), (asset2, 0.3333)])

        for asset in [asset1, asset2]:
            order_lists = blotter.open_orders[asset]
            assert order_lists is not None
            assert 1 == len(order_lists)

        asset1_order = blotter.open_orders[1][0]
        asset2_order = blotter.open_orders[2][0]

        # make sure the asset1 order didn't change
        assert 100 == asset1_order.amount
        assert 10 == asset1_order.limit
        assert 1 == asset1_order.asset

        # make sure the asset2 order did change
        # to 300 shares at 3.33
        assert 300 == asset2_order.amount
        assert 3.33 == asset2_order.limit
        assert 2 == asset2_order.asset
コード例 #4
0
    def initialize(self, *args, **kwargs):
        self.add_transform(MovingAverage,
                           'mavg', ['price'],
                           market_aware=True,
                           window_length=2)

        self.set_slippage(FixedSlippage())
コード例 #5
0
ファイル: test_finance.py プロジェクト: daiab/neutron
    def test_blotter_processes_splits(self):
        blotter = Blotter('daily', equity_slippage=FixedSlippage())

        # set up two open limit orders with very low limit prices,
        # one for sid 1 and one for sid 2
        asset1 = self.asset_finder.retrieve_asset(1)
        asset2 = self.asset_finder.retrieve_asset(2)
        asset133 = self.asset_finder.retrieve_asset(133)

        blotter.order(asset1, 100, LimitOrder(10))
        blotter.order(asset2, 100, LimitOrder(10))

        # send in splits for assets 133 and 2.  We have no open orders for
        # asset 133 so it should be ignored.
        blotter.process_splits([(asset133, 0.5), (asset2, 0.3333)])

        for asset in [asset1, asset2]:
            order_lists = blotter.open_orders[asset]
            self.assertIsNotNone(order_lists)
            self.assertEqual(1, len(order_lists))

        asset1_order = blotter.open_orders[1][0]
        asset2_order = blotter.open_orders[2][0]

        # make sure the asset1 order didn't change
        self.assertEqual(100, asset1_order.amount)
        self.assertEqual(10, asset1_order.limit)
        self.assertEqual(1, asset1_order.asset)

        # make sure the asset2 order did change
        # to 300 shares at 3.33
        self.assertEqual(300, asset2_order.amount)
        self.assertEqual(3.33, asset2_order.limit)
        self.assertEqual(2, asset2_order.asset)
コード例 #6
0
ファイル: test_finance.py プロジェクト: edouardswiac/zipline
    def test_blotter_processes_splits(self):
        blotter = Blotter('daily',
                          self.env.asset_finder,
                          slippage_func=FixedSlippage())

        # set up two open limit orders with very low limit prices,
        # one for sid 1 and one for sid 2
        blotter.order(blotter.asset_finder.retrieve_asset(1), 100,
                      LimitOrder(10))
        blotter.order(blotter.asset_finder.retrieve_asset(2), 100,
                      LimitOrder(10))

        # send in a split for sid 2
        blotter.process_splits([(2, 0.3333)])

        for sid in [1, 2]:
            order_lists = blotter.open_orders[sid]
            self.assertIsNotNone(order_lists)
            self.assertEqual(1, len(order_lists))

        aapl_order = blotter.open_orders[1][0].to_dict()
        fls_order = blotter.open_orders[2][0].to_dict()

        # make sure the aapl order didn't change
        self.assertEqual(100, aapl_order['amount'])
        self.assertEqual(10, aapl_order['limit'])
        self.assertEqual(1, aapl_order['sid'])

        # make sure the fls order did change
        # to 300 shares at 3.33
        self.assertEqual(300, fls_order['amount'])
        self.assertEqual(3.33, fls_order['limit'])
        self.assertEqual(2, fls_order['sid'])
コード例 #7
0
def initialize(context):
    """
    Initialization and trading logic
    """
    # Set comission and slippage
    if enable_commission:
        comm_model = PerDollar(cost=commission_pct)
    else:
        comm_model = PerDollar(cost=0.0)

    set_commission(comm_model)

    if enable_slippage:
        slippage_model = VolumeShareSlippage(
            volume_limit=slippage_volume_limit, price_impact=slippage_impact)
    else:
        slippage_model = FixedSlippage(spread=0.0)

    # Used only for progress output
    context.last_month = initial_portfolio

    # Store index membership
    context.index_members = pd.read_csv('./data/sp500_members.csv',
                                        index_col=0,
                                        parse_dates=[0])

    # Schedule rebalance monthly
    schedule_function(func=rebalance,
                      date_rule=date_rules.month_start(),
                      time_rule=time_rules.market_open())
コード例 #8
0
ファイル: quantop.py プロジェクト: 603382631/QuantFox
 def initialize(self): #,startDate,endDate,startDateTrading,debug):
     self.secs=['SPY','XLY','XLP','XLE','XLF','XLB','XLK','XLV','XLI','XLU']
     self.slippage=FixedSlippage()
     # self.set_commission(commission.PerShare(cost=.005))
     self.leverage = 1.0
     self.top_k = 1
     self.weight = self.leverage/self.top_k
     self.trailing_return= trailing_return(refresh_period=30, window_length=61)
コード例 #9
0
 def initialize(self, window_length=60):
     self.spreads = []
     self.invested = 0
     self.window_length = window_length
     self.ols_transform = ols_transform(refresh_period=1,
                                        window_length=self.window_length)
     self.instant_fill = True
     self.slippage = FixedSlippage(spread=0)
     self.sscore = [
     ]  # store those sscores which can be regarded as the hist
コード例 #10
0
def initialize(context):
    logging.debug('enter initialize')
    context.set_slippage(FixedSlippage())
    context.set_commission(commission.PerTrade(cost=5))

    context.LOW_RSI = initialize.low_RSI
    context.HIGH_RSI = initialize.high_RSI
    context.rsi_window = initialize.rsi_window
    add_history(context.rsi_window, '1d', 'price')
    context.i = 0
    context.invested = False
コード例 #11
0
    def initialize(self, tickers, basket):

        # To keep track of whether we invested in the stock or not

        self.invested = False
        self.commission = PerTrade(0.00)
        #self.starting_cash(10000)
        self.set_slippage(FixedSlippage())

        self.capital_base = 10000
        self.tickers = tickers
        self.basket = basket
        self.quantity = 0
コード例 #12
0
ファイル: test_code.py プロジェクト: animesh0353/trade
    def initialize(self):
        self.invested = False

        self.trade_size = 1000
        self.long = False
        self.short = False
        self.closed = False
        self.trading_day_counter = 0
        self.pct_stop = 0.025
        self.long_stop_price = 0.0
        self.short_stop_price = 0.0
        self.target = 0.05
        commission_cost = self.trade_size * COMMISSION
        self.set_slippage(FixedSlippage(spread=0.10))
        self.set_commission(PerTrade(cost=commission_cost))
コード例 #13
0
    def initialize(self, *args, **kwargs):
        self.refresh_period = kwargs.pop('refresh_period', 2)
        self.window_length = kwargs.pop('window_length', 3)

        self.args = args
        self.kwargs = kwargs

        self.history_return_price_class = []
        self.history_return_price_decorator = []
        self.history_return_args = []
        self.history_return_price_market_aware = []
        self.history_return_more_days_than_refresh = []

        self.return_price_class = ReturnPriceBatchTransform(
            market_aware=False,
            refresh_period=self.refresh_period,
            delta=timedelta(days=self.window_length))

        self.return_price_decorator = return_price_batch_decorator(
            market_aware=False,
            refresh_period=self.refresh_period,
            delta=timedelta(days=self.window_length))

        self.return_args_batch = return_args_batch_decorator(
            market_aware=False,
            refresh_period=self.refresh_period,
            delta=timedelta(days=self.window_length))

        self.return_price_market_aware = ReturnPriceBatchTransform(
            market_aware=True,
            refresh_period=self.refresh_period,
            window_length=self.window_length)

        self.return_price_more_days_than_refresh = ReturnPriceBatchTransform(
            market_aware=True, refresh_period=1, window_length=3)

        self.set_slippage(FixedSlippage())
コード例 #14
0
ファイル: trading.py プロジェクト: zbanga/abund.com
    def run(self,
            algo,
            tBeg=None,
            tEnd=None,
            commission=None,
            slippage=None,
            warn=False,
            bar_source='yahoo',
            adjusted=True,
            data_frequency='daily',
            include_open=True,
            csi_port='ETFs'):

        # Set a default algo if none is provided
        if not algo:
            raise Exception('No algo provided')
        self.algo = algo

        # set commission model
        if commission:
            self.algo.set_commission(commission)
        else:
            self.algo.set_commission(
                PerShareWithMin(comm_per_share=0.01, comm_min=1.0))

        # set slippage model
        if slippage:
            self.algo.set_slippage(slippage)
        else:
            self.algo.set_slippage(FixedSlippage(spread=0.0))

        # guess starting and ending dates if none are provided
        if not tEnd:
            tEnd = get_end_date()
        if not tBeg:
            tBeg = get_start_date(self.algo.iL, tNow=tEnd)

        tBeg = pytz.utc.localize(tBeg)
        tEnd = pytz.utc.localize(tEnd)

        self.sim_params = SimulationParameters(tBeg,
                                               tEnd,
                                               data_frequency=data_frequency,
                                               capital_base=self.capital_base,
                                               make_new_environment=True,
                                               extra_dates=[])
        # print self.sim_params

        source = self.get_bar_source(tBeg,
                                     tEnd,
                                     bar_source,
                                     adjusted=adjusted,
                                     include_open=include_open,
                                     csi_port=csi_port)

        if bar_source == 'redshift':
            bench_source, self.bench_price_utc = redshift.get_bench_source(
                tBeg, tEnd)
        else:
            bench_source = None

        sources = [source]

        if not warn:
            # turn off warnings
            import warnings
            warnings.filterwarnings('ignore')

        self.run_time = time.time()
        self.results = self.algo.run(sources,
                                     sim_params=self.sim_params,
                                     benchmark_return_source=bench_source)
        self.run_time = time.time() - self.run_time
コード例 #15
0
    def test_order_rejection(self):
        blotter = SimulationBlotter(self.sim_params)

        # Reject a nonexistent order -> no order appears in new_order,
        # no exceptions raised out
        blotter.reject(56)
        self.assertEqual(blotter.new_orders, [])

        # Basic tests of open order behavior
        open_order_id = blotter.order(self.asset_24, 100, MarketOrder())
        second_order_id = blotter.order(self.asset_24, 50, MarketOrder())
        self.assertEqual(len(blotter.open_orders[self.asset_24]), 2)
        open_order = blotter.open_orders[self.asset_24][0]
        self.assertEqual(open_order.status, ORDER_STATUS.OPEN)
        self.assertEqual(open_order.id, open_order_id)
        self.assertIn(open_order, blotter.new_orders)

        # Reject that order immediately (same bar, i.e. still in new_orders)
        blotter.reject(open_order_id)
        self.assertEqual(len(blotter.new_orders), 2)
        self.assertEqual(len(blotter.open_orders[self.asset_24]), 1)
        still_open_order = blotter.new_orders[0]
        self.assertEqual(still_open_order.id, second_order_id)
        self.assertEqual(still_open_order.status, ORDER_STATUS.OPEN)
        rejected_order = blotter.new_orders[1]
        self.assertEqual(rejected_order.status, ORDER_STATUS.REJECTED)
        self.assertEqual(rejected_order.reason, '')

        # Do it again, but reject it at a later time (after tradesimulation
        # pulls it from new_orders)
        blotter = SimulationBlotter(self.sim_params)
        new_open_id = blotter.order(self.asset_24, 10, MarketOrder())
        new_open_order = blotter.open_orders[self.asset_24][0]
        self.assertEqual(new_open_id, new_open_order.id)
        # Pretend that the trade simulation did this.
        blotter.new_orders = []

        rejection_reason = "Not enough cash on hand."
        blotter.reject(new_open_id, reason=rejection_reason)
        rejected_order = blotter.new_orders[0]
        self.assertEqual(rejected_order.id, new_open_id)
        self.assertEqual(rejected_order.status, ORDER_STATUS.REJECTED)
        self.assertEqual(rejected_order.reason, rejection_reason)

        # You can't reject a filled order.
        # Reset for paranoia
        blotter = SimulationBlotter(self.sim_params)
        blotter.slippage_models[Equity] = FixedSlippage()
        filled_id = blotter.order(self.asset_24, 100, MarketOrder())
        filled_order = None
        blotter.current_dt = self.sim_params.sessions[-1]
        bar_data = self.create_bardata(
            simulation_dt_func=lambda: self.sim_params.sessions[-1], )
        txns, _, closed_orders = blotter.get_transactions(bar_data)
        for txn in txns:
            filled_order = blotter.orders[txn.order_id]
        blotter.prune_orders(closed_orders)

        self.assertEqual(filled_order.id, filled_id)
        self.assertIn(filled_order, blotter.new_orders)
        self.assertEqual(filled_order.status, ORDER_STATUS.FILLED)
        self.assertNotIn(filled_order, blotter.open_orders[self.asset_24])

        blotter.reject(filled_id)
        updated_order = blotter.orders[filled_id]
        self.assertEqual(updated_order.status, ORDER_STATUS.FILLED)
コード例 #16
0
 def setUp(self):
     self.zipline_test_config = {'sid': 133, 'slippage': FixedSlippage()}
     setup_logger(self)
コード例 #17
0
 def initialize(self):
     # Moving window. Defining maxlen causes the window length 
     # to remain constant as old events get dropped once full.
     self.window = deque(maxlen=delta_t)
     # Turns off slippage to simplify simulation.
     self.set_slippage(FixedSlippage())
コード例 #18
0
ファイル: test_finance.py プロジェクト: edouardswiac/zipline
    def transaction_sim(self, **params):
        """ This is a utility method that asserts expected
        results for conversion of orders to transactions given a
        trade history"""
        tempdir = TempDirectory()
        try:
            trade_count = params['trade_count']
            trade_interval = params['trade_interval']
            order_count = params['order_count']
            order_amount = params['order_amount']
            order_interval = params['order_interval']
            expected_txn_count = params['expected_txn_count']
            expected_txn_volume = params['expected_txn_volume']

            # optional parameters
            # ---------------------
            # if present, alternate between long and short sales
            alternate = params.get('alternate')

            # if present, expect transaction amounts to match orders exactly.
            complete_fill = params.get('complete_fill')

            env = TradingEnvironment()

            sid = 1

            if trade_interval < timedelta(days=1):
                sim_params = factory.create_simulation_parameters(
                    data_frequency="minute")

                minutes = env.market_minute_window(
                    sim_params.first_open,
                    int((trade_interval.total_seconds() / 60) * trade_count) +
                    100)

                price_data = np.array([10.1] * len(minutes))
                assets = {
                    sid:
                    pd.DataFrame({
                        "open": price_data,
                        "high": price_data,
                        "low": price_data,
                        "close": price_data,
                        "volume": np.array([100] * len(minutes)),
                        "dt": minutes
                    }).set_index("dt")
                }

                write_bcolz_minute_data(
                    env, env.days_in_range(minutes[0], minutes[-1]),
                    tempdir.path, assets)

                equity_minute_reader = BcolzMinuteBarReader(tempdir.path)

                data_portal = DataPortal(
                    env,
                    equity_minute_reader=equity_minute_reader,
                )
            else:
                sim_params = factory.create_simulation_parameters(
                    data_frequency="daily")

                days = sim_params.trading_days

                assets = {
                    1:
                    pd.DataFrame(
                        {
                            "open": [10.1] * len(days),
                            "high": [10.1] * len(days),
                            "low": [10.1] * len(days),
                            "close": [10.1] * len(days),
                            "volume": [100] * len(days),
                            "day": [day.value for day in days]
                        },
                        index=days)
                }

                path = os.path.join(tempdir.path, "testdata.bcolz")
                DailyBarWriterFromDataFrames(assets).write(path, days, assets)

                equity_daily_reader = BcolzDailyBarReader(path)

                data_portal = DataPortal(
                    env,
                    equity_daily_reader=equity_daily_reader,
                )

            if "default_slippage" not in params or \
               not params["default_slippage"]:
                slippage_func = FixedSlippage()
            else:
                slippage_func = None

            blotter = Blotter(sim_params.data_frequency, self.env.asset_finder,
                              slippage_func)

            env.write_data(
                equities_data={
                    sid: {
                        "start_date": sim_params.trading_days[0],
                        "end_date": sim_params.trading_days[-1]
                    }
                })

            start_date = sim_params.first_open

            if alternate:
                alternator = -1
            else:
                alternator = 1

            tracker = PerformanceTracker(sim_params, self.env)

            # replicate what tradesim does by going through every minute or day
            # of the simulation and processing open orders each time
            if sim_params.data_frequency == "minute":
                ticks = minutes
            else:
                ticks = days

            transactions = []

            order_list = []
            order_date = start_date
            for tick in ticks:
                blotter.current_dt = tick
                if tick >= order_date and len(order_list) < order_count:
                    # place an order
                    direction = alternator**len(order_list)
                    order_id = blotter.order(
                        blotter.asset_finder.retrieve_asset(sid),
                        order_amount * direction, MarketOrder())
                    order_list.append(blotter.orders[order_id])
                    order_date = order_date + order_interval
                    # move after market orders to just after market next
                    # market open.
                    if order_date.hour >= 21:
                        if order_date.minute >= 00:
                            order_date = order_date + timedelta(days=1)
                            order_date = order_date.replace(hour=14, minute=30)
                else:
                    bar_data = BarData(data_portal, lambda: tick,
                                       sim_params.data_frequency)
                    txns, _ = blotter.get_transactions(bar_data)
                    for txn in txns:
                        tracker.process_transaction(txn)
                        transactions.append(txn)

            for i in range(order_count):
                order = order_list[i]
                self.assertEqual(order.sid, sid)
                self.assertEqual(order.amount, order_amount * alternator**i)

            if complete_fill:
                self.assertEqual(len(transactions), len(order_list))

            total_volume = 0
            for i in range(len(transactions)):
                txn = transactions[i]
                total_volume += txn.amount
                if complete_fill:
                    order = order_list[i]
                    self.assertEqual(order.amount, txn.amount)

            self.assertEqual(total_volume, expected_txn_volume)

            self.assertEqual(len(transactions), expected_txn_count)

            cumulative_pos = tracker.position_tracker.positions[sid]
            if total_volume == 0:
                self.assertIsNone(cumulative_pos)
            else:
                self.assertEqual(total_volume, cumulative_pos.amount)

            # the open orders should not contain sid.
            oo = blotter.open_orders
            self.assertNotIn(sid, oo, "Entry is removed when no open orders")
        finally:
            tempdir.cleanup()
コード例 #19
0
    def initialize(self, *args, **kwargs):
        self.refresh_period = kwargs.pop('refresh_period', 1)
        self.window_length = kwargs.pop('window_length', 3)

        self.args = args
        self.kwargs = kwargs

        self.history_return_price_class = []
        self.history_return_price_decorator = []
        self.history_return_args = []
        self.history_return_arbitrary_fields = []
        self.history_return_nan = []
        self.history_return_sid_filter = []
        self.history_return_field_filter = []
        self.history_return_field_no_filter = []
        self.history_return_ticks = []
        self.history_return_not_full = []

        self.return_price_class = ReturnPriceBatchTransform(
            refresh_period=self.refresh_period,
            window_length=self.window_length,
            clean_nans=False)

        self.return_price_decorator = return_price_batch_decorator(
            refresh_period=self.refresh_period,
            window_length=self.window_length,
            clean_nans=False)

        self.return_args_batch = return_args_batch_decorator(
            refresh_period=self.refresh_period,
            window_length=self.window_length,
            clean_nans=False)

        self.return_arbitrary_fields = return_data(
            refresh_period=self.refresh_period,
            window_length=self.window_length,
            clean_nans=False)

        self.return_nan = return_price_batch_decorator(
            refresh_period=self.refresh_period,
            window_length=self.window_length,
            clean_nans=True)

        self.return_sid_filter = return_price_batch_decorator(
            refresh_period=self.refresh_period,
            window_length=self.window_length,
            clean_nans=True,
            sids=[0])

        self.return_field_filter = return_data(
            refresh_period=self.refresh_period,
            window_length=self.window_length,
            clean_nans=True,
            fields=['price'])

        self.return_field_no_filter = return_data(
            refresh_period=self.refresh_period,
            window_length=self.window_length,
            clean_nans=True)

        self.return_not_full = return_data(refresh_period=0,
                                           window_length=self.window_length,
                                           compute_only_full=False)

        self.uses_ufunc = uses_ufunc(refresh_period=self.refresh_period,
                                     window_length=self.window_length,
                                     clean_nans=False)

        self.price_multiple = price_multiple(
            refresh_period=self.refresh_period,
            window_length=self.window_length,
            clean_nans=False)

        self.iter = 0

        self.set_slippage(FixedSlippage())
コード例 #20
0
 def initialize(self, window_length=100):
     self.set_slippage(FixedSlippage())
     self.invested = False
     self.regression_transform = regression_transform(refresh_period=500,
                                                      window_length=window_length)
コード例 #21
0
    def test_order_rejection(self):
        blotter = SimulationBlotter()

        # Reject a nonexistent order -> no order appears in new_order,
        # no exceptions raised out
        blotter.reject(56)
        assert blotter.new_orders == []

        # Basic tests of open order behavior
        open_order_id = blotter.order(self.asset_24, 100, MarketOrder())
        second_order_id = blotter.order(self.asset_24, 50, MarketOrder())
        assert len(blotter.open_orders[self.asset_24]) == 2
        open_order = blotter.open_orders[self.asset_24][0]
        assert open_order.status == ORDER_STATUS.OPEN
        assert open_order.id == open_order_id
        assert open_order in blotter.new_orders

        # Reject that order immediately (same bar, i.e. still in new_orders)
        blotter.reject(open_order_id)
        assert len(blotter.new_orders) == 2
        assert len(blotter.open_orders[self.asset_24]) == 1
        still_open_order = blotter.new_orders[0]
        assert still_open_order.id == second_order_id
        assert still_open_order.status == ORDER_STATUS.OPEN
        rejected_order = blotter.new_orders[1]
        assert rejected_order.status == ORDER_STATUS.REJECTED
        assert rejected_order.reason == ""

        # Do it again, but reject it at a later time (after tradesimulation
        # pulls it from new_orders)
        blotter = SimulationBlotter()
        new_open_id = blotter.order(self.asset_24, 10, MarketOrder())
        new_open_order = blotter.open_orders[self.asset_24][0]
        assert new_open_id == new_open_order.id
        # Pretend that the trade simulation did this.
        blotter.new_orders = []

        rejection_reason = "Not enough cash on hand."
        blotter.reject(new_open_id, reason=rejection_reason)
        rejected_order = blotter.new_orders[0]
        assert rejected_order.id == new_open_id
        assert rejected_order.status == ORDER_STATUS.REJECTED
        assert rejected_order.reason == rejection_reason

        # You can't reject a filled order.
        # Reset for paranoia
        blotter = SimulationBlotter()
        blotter.slippage_models[Equity] = FixedSlippage()
        filled_id = blotter.order(self.asset_24, 100, MarketOrder())
        filled_order = None
        blotter.current_dt = self.sim_params.sessions[-1]
        bar_data = self.create_bardata(
            simulation_dt_func=lambda: self.sim_params.sessions[-1], )
        txns, _, closed_orders = blotter.get_transactions(bar_data)
        for txn in txns:
            filled_order = blotter.orders[txn.order_id]
        blotter.prune_orders(closed_orders)

        assert filled_order.id == filled_id
        assert filled_order in blotter.new_orders
        assert filled_order.status == ORDER_STATUS.FILLED
        assert filled_order not in blotter.open_orders[self.asset_24]

        blotter.reject(filled_id)
        updated_order = blotter.orders[filled_id]
        assert updated_order.status == ORDER_STATUS.FILLED