Ejemplo n.º 1
0
    def __init__(self,
                 data_source,
                 look_backward_window=1,
                 mode="rl",
                 starting_cash={"STOCK": 1000000},
                 commission_multiplier=1,
                 min_commission=5,
                 tax_multiplier=1) -> None:

        self.look_backward_window = look_backward_window
        self.mode = mode
        self.starting_cash = starting_cash
        self.commission_multiplier = commission_multiplier
        self.min_commission = min_commission
        self.tax_multiplier = tax_multiplier

        self._context = Context(look_backward_window=look_backward_window)

        #set data_source
        self._context.set_data_source(data_source)

        #set event_source
        event_source = SimulationEventSource()
        self._context.set_event_source(event_source)

        #set broker
        broker = SimulationBroker(self._context)
        self._context.set_broker(broker)

        # transaction_cost decider
        transaction_cost_decider = CNStockTransactionCostDecider(
            commission_multiplier=commission_multiplier,
            min_commission=min_commission,
            tax_multiplier=tax_multiplier)
        self._context.set_transaction_cost_decider("CS",
                                                   transaction_cost_decider)

        # setup account and portfolio
        portfolio = Portfolio(starting_cash=starting_cash, init_positions={})
        self._context.set_portfolio(portfolio)

        # setup a tracker to record key info
        tracker = Tracker(self._context)
        self._context.set_tracker(tracker)
        self._context.event_bus.publish_event(Event(EVENT.POST_SYSTEM_INIT))

        #setUP executor
        if mode == "rl":
            self._executor = RLExecutor(self._context)
        else:
            self._executor = Executor(self._context)

        # user strategy
        user_strategy = Strategy(self._context)
Ejemplo n.º 2
0
    def __init__(self, commission_rate, commission_multiplier, min_commission):
        self.commission_rate = commission_rate
        self.commission_multiplier = commission_multiplier
        self.commission_map = defaultdict(lambda: min_commission)
        self.min_commission = min_commission

        self.context = Context.get_instance()
Ejemplo n.º 3
0
    def __from_create__(
            cls, order_id, price, amount, side, position_effect, order_book_id, commission=0., tax=0.,
            trade_id=None, close_today_amount=0, frozen_price=0, calendar_dt=None, trading_dt=None
    ):

        trade = cls()
        trade_id = trade_id or next(trade.trade_id_gen)

        for value in (price, amount, commission, tax, frozen_price):
            if value != value:
                raise RuntimeError(
                    "price, amount, commission, tax and frozen_price of trade {trade_id} is not supposed to be nan, current_value is {price}, {amount}, {commission}, {tax}, {frozen_price}"
                .format(
                    trade_id=trade_id, price=price, amount=amount, commission=commission, tax=tax,
                    frozen_price=frozen_price
                ))

        context = Context.get_instance()
        trade._calendar_dt = calendar_dt or context.calendar_dt
        trade._trading_dt = trading_dt or context.trading_dt
        trade._price = price
        trade._amount = amount
        trade._order_id = order_id
        trade._commission = commission
        trade._tax = tax
        trade._trade_id = trade_id
        trade._close_today_amount = close_today_amount
        trade._side = side
        trade._position_effect = position_effect
        trade._order_book_id = order_book_id
        trade._frozen_price = frozen_price
        return trade
Ejemplo n.º 4
0
 def last_price(self):
     if self._last_price != self._last_price:
         context = Context.get_instance()
         self._last_price = context.get_last_price(self._order_book_id)
         if self._last_price != self._last_price:
             raise RuntimeError("last price of position {} is not supposed to be nan".format(self._order_book_id))
     return self._last_price
Ejemplo n.º 5
0
    def _on_settlement(self, event):
        trading_date = Context.get_instance().trading_dt.date()

        for order_book_id, positions in list(self._positions.items()):
            for position in six.itervalues(positions):
                #print(trading_date)
                #print(position)
                delta_cash = position.settlement(trading_date)
                #print(delta_cash)
                self._total_cash += delta_cash

        for order_book_id, positions in list(self._positions.items()):
            if all(p.quantity == 0 and p.equity == 0
                   for p in six.itervalues(positions)):
                del self._positions[order_book_id]

        self._backward_trade_set.clear()

        # if total_value <= 0, forced_liquidation
        forced_liquidation = True  #Environment.get_instance().config.base.forced_liquidation
        if self.total_value <= 0 and forced_liquidation:
            if self._positions:
                print("Trigger Forced Liquidation, current total_value is 0")
            self._positions.clear()
            self._total_cash = 0
Ejemplo n.º 6
0
 def get_current_trading_dt_total_value(self):
     # this method is stateless operation
     total_equity = 0
     for p in self._iter_pos():
         if p.quantity !=0:
             price = Context.get_instance().get_last_price(p.order_book_id)
             total_equity += price * p.quantity
     return self._total_cash + total_equity
Ejemplo n.º 7
0
 def _update_last_price(self, _):
     context = Context.get_instance()
     #print("_update_last_price", context.trading_dt)
     for order_book_id, positions in self._positions.items():
         price = context.get_last_price(order_book_id)
         if price == price:
             for position in six.itervalues(positions):
                 #print("before update last price \n {}".format(position))
                 position.update_last_price(price)
Ejemplo n.º 8
0
def order_target_quantities(target_quantities: Dict[str, int]) -> List[Order]:
    """
    make the account position to touch the target quantities
    :param target_quantities: a dictionary contain the target quantities of position
    :example:
    .. code-block:: python
        # adjust positions, to make the '000001.XSHE' to touch the target quantities 800
        # make the '000002.XSHE' to touch the target quantities 400 
        order_target_quantities({
            '000001.XSHE': 800
            '000002.XSHE': 400
        })
    """

    context = Context.get_instance()
    account = context.portfolio.accounts[DEFAULT_ACCOUNT_TYPE.STOCK]

    close_orders, open_orders = [], []
    current_quantities = {
        p.order_book_id: p.quantity
        for p in account.get_positions()
        if p.direction == POSITION_DIRECTION.LONG
    }

    # close all position if the order_book_id not in the key list of target_quantities
    for order_book_id, quantity in current_quantities.items():
        if order_book_id not in target_quantities:
            close_orders.append(
                Order.__from_create__(order_book_id, quantity, SIDE.SELL,
                                      MarketOrder(), POSITION_EFFECT.CLOSE))

    round_lot = 100
    for order_book_id, target_quantity in target_quantities.items():
        if order_book_id in current_quantities:
            delta_quantity = target_quantity - current_quantities[order_book_id]
        else:
            delta_quantity = target_quantity

        if delta_quantity >= round_lot:
            delta_quantity = math.floor(delta_quantity / round_lot) * round_lot
            open_orders.append(
                Order.__from_create__(order_book_id, delta_quantity, SIDE.BUY,
                                      MarketOrder(), POSITION_EFFECT.OPEN))
        elif delta_quantity < -1:
            delta_quantity = math.floor(delta_quantity)
            close_orders.append(
                Order.__from_create__(order_book_id,
                                      abs(delta_quantity), SIDE.SELL,
                                      MarketOrder(), POSITION_EFFECT.CLOSE))

    to_submit_orders = []
    for order in chain(close_orders, open_orders):
        #print("to submit order: {}".format(order))
        to_submit_orders.append(order)
    return to_submit_orders
Ejemplo n.º 9
0
def get_positions() -> List[Position]:
    """
    get all available positions,
    :example:
    ..  code-block:: python3
        [In] get_positions()
        [Out]
        [BookingPosition({'order_book_id': '000014.XSHE', 'quantity': 100, 'direction': POSITION_DIRECTION.LONG, 'old_quantity': 0, 'trading_pnl': 1.0, 'avg_price': 9.56, 'last_price': 0, 'position_pnl': 0.0}),
         BookingPosition({'order_book_id': '000010.XSHE', 'quantity': 100, 'direction': POSITION_DIRECTION.LONG, 'old_quantity': 0, 'trading_pnl': 0.0, 'avg_price': 3.09, 'last_price': 0, 'position_pnl': 0.0})]
    """
    portfolio = Context.get_instance().portfolio
    return portfolio.get_positions()
Ejemplo n.º 10
0
    def test_senond_step_sell(self):
        to_submit_orders = order_target_weights({self.order_book_id: 0.2})
        state, reward, is_done, info = self.env.step(action=to_submit_orders)

        order = to_submit_orders[0]
        # this is a sell trade
        #pdb.set_trace()
        self.assertEqual(first=order.side, second=SIDE.SELL)
        #
        second_trading_dt = self.trading_dts[1]
        expect_deal_price = self.data_source.get_last_price(
            order_book_id=self.order_book_id, dt=second_trading_dt)
        expect_deal_money = expect_deal_price * order.quantity

        expect_commission_fee = expect_deal_money * self.commission_rate * self.commission_multiplier
        expect_tax = expect_deal_money * self.tax_rate * self.tax_multiplier  # no tax rate when buy
        expect_transaction_cost = expect_commission_fee + expect_tax
        print("expect_transaction_cost: {}".format(expect_transaction_cost))
        second_trade = Context.get_instance().tracker._trades[1]
        print(second_trade)
        self.assertEqual(first=second_trade["order_book_id"],
                         second=self.order_book_id)
        self.assertEqual(
            first=second_trade["trading_datetime"],
            second=second_trading_dt.strftime("%Y-%m-%d %H:%M:%S"))
        self.assertEqual(first=second_trade["last_price"],
                         second=expect_deal_price)
        self.assertEqual(first=second_trade["commission"],
                         second=expect_commission_fee)
        self.assertEqual(first=second_trade["tax"], second=expect_tax)
        self.assertEqual(first=second_trade["transaction_cost"],
                         second=expect_transaction_cost)

        expect_cash_stock_settlement = self.expect_cash_stock_settlement + expect_deal_money - expect_transaction_cost

        next_trading_dt = self.trading_dts[2]
        expect_settlement_price = self.data_source.get_last_price(
            order_book_id=self.order_book_id, dt=next_trading_dt)
        expect_remaining_market_value_stock_settlement = (
            self.first_trade["last_quantity"] -
            second_trade["last_quantity"]) * expect_settlement_price

        self.expect_total_value_stock_settlement = expect_cash_stock_settlement + expect_remaining_market_value_stock_settlement

        self.expect_total_value_future_settlement = self.expect_total_value_future

        expect_total_value_settlement = self.expect_total_value_stock_settlement + self.expect_total_value_future_settlement

        expect_reward = (expect_total_value_settlement -
                         self.expect_total_value_settlement
                         ) / self.expect_total_value_settlement
        #pdb.set_trace()
        self.assertAlmostEqual(first=reward, second=expect_reward)
Ejemplo n.º 11
0
    def register_event(self):
        event_bus = Context.get_instance().event_bus
        event_bus.add_listener(
            EVENT.TRADE, lambda e: self.apply_trade(e.trade, e.order) if e.account == self else None
        )
        event_bus.add_listener(EVENT.ORDER_PENDING_NEW, self._on_order_pending_new)
        event_bus.add_listener(EVENT.ORDER_CREATION_REJECT, self._on_order_unsolicited_update)
        event_bus.add_listener(EVENT.ORDER_UNSOLICITED_UPDATE, self._on_order_unsolicited_update)
        #event_bus.add_listener(EVENT.ORDER_CANCELLATION_PASS, self._on_order_unsolicited_update)

        event_bus.add_listener(EVENT.PRE_BEFORE_TRADING, self._on_before_trading)
        event_bus.add_listener(EVENT.SETTLEMENT, self._on_settlement)

        event_bus.prepend_listener(EVENT.PRE_BAR, self._update_last_price)
Ejemplo n.º 12
0
    def test_trading_dts_setup(self):
        #test available trading dts
        all_trading_dts = self.data_source.get_available_trading_dts()
        expected_available_trading_dts = all_trading_dts[self.
                                                         look_backward_window -
                                                         1:]
        actual_available_trading_dts = Context.get_instance(
        ).get_available_trading_dts()
        self.assertListEqual(list(actual_available_trading_dts),
                             list(expected_available_trading_dts))

        #test the first trading dt
        expected_first_trading_dt = expected_available_trading_dts[0]
        actual_first_trading_dt = Context.get_instance().trading_dt
        self.assertEqual(actual_first_trading_dt, expected_first_trading_dt)

        order_book_ids = self.data_source.get_available_order_book_ids()

        expected_first_last_price = self.data_source.get_last_price(
            order_book_id=order_book_ids[0], dt=expected_first_trading_dt)
        actual_first_last_price = Context.get_instance().get_last_price(
            order_book_id=order_book_ids[0])
        self.assertEqual(actual_first_last_price, expected_first_last_price)
Ejemplo n.º 13
0
def is_cash_enough(order, account, warn=True):
    order_cost = order.frozen_price * order.quantity  #instrument.calc_cash_occupation(order.frozen_price, order.quantity, order.position_direction)
    order_cost += Context.get_instance().get_order_transaction_cost(order)
    if order_cost <= account.cash:
        return True
    if warn:
        print(
            "Order Creation Failed: not enough money to buy {order_book_id}, needs {cost_money:.2f},"
            " cash {cash:.2f}").format(
                order_book_id=order.order_book_id,
                cost_money=order_cost,
                cash=account.cash,
            )
    return False
Ejemplo n.º 14
0
def get_position(
        order_book_id: str,
        direction: POSITION_DIRECTION = POSITION_DIRECTION.LONG) -> Position:
    """
    get the position object from one specific order_book_id,
    :param order_book_id: 
    :param direction:
    :example:
    ..  code-block:: python3
        [In] get_position('000014.XSHE','long_positions")
        [Out]
        [BookingPosition({'order_book_id': '000014.XSHE', 'quantity': 100, 'direction': POSITION_DIRECTION.LONG, 'old_quantity': 0, 'trading_pnl': 1.0, 'avg_price': 9.56, 'last_price': 0, 'position_pnl': 0.0})]
    """
    portfolio = Context.get_instance().portfolio
    return portfolio.get_position(order_book_id, direction)
Ejemplo n.º 15
0
def _submit_order(order_book_id, amount, side, position_effect, style,
                  quantity, auto_switch_order_value):
    # param: amount: the target quantity of this order
    # param: quantity: the quantity of exist position of order_book_id
    context = Context.get_instance()
    if isinstance(style, LimitOrder):
        if not is_valid_price(style.get_limit_price()):
            raise RuntimeError((u"Limit order price should be positive"))
    price = context.get_last_price(order_book_id)
    if not is_valid_price(price):
        print("Order Creation Failed: [{order_book_id}] No market data"
              ).format(order_book_id=order_book_id)
        return
    round_lot = 100

    if side in [SIDE.BUY, side.SELL]:
        if not (side == SIDE.SELL and quantity == abs(amount)):
            # KSH can buy(sell) 201, 202 shares
            amount = int(Decimal(amount) / Decimal(round_lot)) * round_lot

    if amount == 0:
        print(
            "Order Creation Failed: 0 order quantity, order_book_id={order_book_id}"
        ).format(order_book_id=order_book_id)
        return
    order = Order.__from_create__(order_book_id, abs(amount), side, style,
                                  position_effect)
    if order.type == ORDER_TYPE.MARKET:
        order.set_frozen_price(price)
    if side == SIDE.BUY and auto_switch_order_value:
        account, position = _get_account_position_ins(order_book_id)
        if not is_cash_enough(order, account):
            print(
                "insufficient cash, use all remaining cash({}) to create order"
            ).format(account.cash)
            return _order_value(account, position, order_book_id, account.cash,
                                style)
    return order
Ejemplo n.º 16
0
def _order_value(account, position, order_book_id, cash_amount, style):
    context = Context.get_instance()
    if cash_amount > 0:
        cash_amount = min(cash_amount, account.cash)
    if isinstance(style, LimitOrder):
        price = style.get_limit_price()
    else:
        price = context.get_last_price(order_book_id)
        if not is_valid_price(price):
            print("Order Creation Failed: [{order_book_id}] No market data"
                  ).format(order_book_id=order_book_id)
            return

    amount = int(Decimal(cash_amount) / Decimal(price))

    round_lot = 100  #int(ins.round_lot)
    if cash_amount > 0:
        amount = int(Decimal(amount) / Decimal(round_lot)) * round_lot
        while amount > 0:
            expected_transaction_cost = context.get_order_transaction_cost(
                Order.__from_create__(order_book_id, amount, SIDE.BUY,
                                      LimitOrder(price), POSITION_EFFECT.OPEN))
            if amount * price + expected_transaction_cost <= cash_amount:
                break
            amount -= round_lot
        else:
            print("Order Creation Failed: 0 order quantity")
            return

    if amount < 0:
        amount = max(amount, -position.closable)

    return _order_shares(order_book_id,
                         amount,
                         style,
                         position.quantity,
                         auto_switch_order_value=False)
Ejemplo n.º 17
0
 def __from_create__(cls, order_book_id, quantity, side, style,
                     position_effect, **kwargs):
     context = Context.get_instance()
     order = cls()
     order._order_id = next(order.order_id_gen)
     order._calendar_dt = context.calendar_dt
     order._trading_dt = context.trading_dt
     order._quantity = quantity
     order._order_book_id = order_book_id
     order._side = side
     order._position_effect = position_effect
     order._message = ""
     order._filled_quantity = 0
     order._status = ORDER_STATUS.PENDING_NEW
     if isinstance(style, LimitOrder):
         order._frozen_price = style.get_limit_price()
         order._type = ORDER_TYPE.LIMIT
     else:
         order._frozen_price = 0.
         order._type = ORDER_TYPE.MARKET
     order._avg_price = 0
     order._transaction_cost = 0
     order._kwargs = kwargs
     return order
Ejemplo n.º 18
0
 def _get_tax(self, order_book_id, side, cost_money):
     instrument_type = Context.get_instance().data_source.instrument_type(
         order_book_id)
     if instrument_type != 'CS':
         return 0
     return cost_money * self.tax_rate * self.tax_multiplier if side == SIDE.SELL else 0
Ejemplo n.º 19
0
def order_target_weights(target_weights: Dict[str, float]) -> List[Order]:
    """
    make the account position to touch the target position
    :param target_weights: a dictionary contain the target weight of position
    :example:
    .. code-block:: python
        # adjust positions, to make the '000001.XSHE' to touch the target percent of account 10%
        # make the '000002.XSHE' to touch the target percent of account 15% 
        order_target_weights({
            '000001.XSHE': 0.1
            '000002.XSHE': 0.15
        })
    """

    total_percent = sum(six.itervalues(target_weights))
    if total_percent > 1 and not np.isclose(total_percent, 1):
        raise RuntimeError("total percent should be lower than 1, current: {}"
                           ).format(total_percent)

    context = Context.get_instance()
    account = context.portfolio.accounts[DEFAULT_ACCOUNT_TYPE.STOCK]
    account_value = account.get_current_trading_dt_total_value()

    #
    target_quantities = {}
    for order_book_id, target_percent in target_weights.items():

        if target_percent < 0:
            raise RuntimeError(
                "target percent of {} should between 0 and 1, current: {}".
                format(order_book_id, target_percent))
        price = context.get_last_price(order_book_id)
        #print("trading_dt:{} current price: {}".format(context.trading_dt, price))
        if not is_valid_price(price):
            print("Order Creation Failed: [{order_book_id}] No market data".
                  format(order_book_id=order_book_id))

            continue
        target_quantity = account_value * target_percent / price
        target_quantities[order_book_id] = int(
            round(target_quantity / 100) * 100)  #target_quantity#

    close_orders, open_orders = [], []
    current_quantities = {
        p.order_book_id: p.quantity
        for p in account.get_positions()
        if p.direction == POSITION_DIRECTION.LONG
    }
    for order_book_id, quantity in current_quantities.items():
        if order_book_id not in target_weights:
            close_orders.append(
                Order.__from_create__(order_book_id, quantity, SIDE.SELL,
                                      MarketOrder(), POSITION_EFFECT.CLOSE))

    round_lot = 100
    for order_book_id, target_quantity in target_quantities.items():
        if order_book_id in current_quantities:
            delta_quantity = target_quantity - current_quantities[order_book_id]
        else:
            delta_quantity = target_quantity

        if delta_quantity >= round_lot:
            delta_quantity = math.floor(delta_quantity / round_lot) * round_lot
            open_orders.append(
                Order.__from_create__(order_book_id, delta_quantity, SIDE.BUY,
                                      MarketOrder(), POSITION_EFFECT.OPEN))
        elif delta_quantity < -1:
            delta_quantity = math.floor(delta_quantity)
            close_orders.append(
                Order.__from_create__(order_book_id,
                                      abs(delta_quantity), SIDE.SELL,
                                      MarketOrder(), POSITION_EFFECT.CLOSE))

    to_submit_orders = []
    for order in chain(close_orders, open_orders):
        #print("to submit order: {}".format(order))
        to_submit_orders.append(order)
    return to_submit_orders
Ejemplo n.º 20
0
    def test_first_step_buy_and_then_sell(self):
        feature_df, price_s = create_toy_feature(order_book_ids_number=1,
                                                 feature_number=3,
                                                 random_seed=111)
        data_source = DataSource(feature_df=feature_df, price_s=price_s)
        order_book_ids = data_source.get_available_order_book_ids()

        STOCK_INIT_CASH = 1000000
        FUTURE_INIT_CASH = 10000
        starting_cash = {"STOCK": STOCK_INIT_CASH, "FUTURE": FUTURE_INIT_CASH}
        commission_rate = 0.0005  #default value in environment
        tax_rate = 0.001  #default value in environment

        commission_multiplier = 2
        min_commission = 5
        tax_multiplier = 1
        """
         
        MANUALly check
        
        first date: 
            target weight: 0.5
            price at end: 77.53
            
            target quantity: 6400
            deal_money = 6400 * 77.53 = 496192
            commition_fee_total = 496.192
            availabel_cash_stock = 1000000 - 496192 - 496.192 = 503311.808
            total_value_account_stock = 496192 + 503311.808 = 999503.808
            total_value_account = 999503.808 + 10000 = 1009503.808
            returns = 1009503.808/1010000  -1 = -0.0004912792079208028
        
        second date:
            target weight: 0.2
            price at end: 69.78
            
            stock_account_at_this_time: 6400*69.78 + 503311.808 =  949903.808
            target quantity: 2700
            to_trade_quantity: 3700
            deal_money = 3700 * 69.78 = 258186
            commition_fee_total = 258186 * (0.001 + 0.001) = 516.372
            
            available_cash_stock = 503311.808 + 258186 - 516.372 = 760981.436
            
            total_value_account_stock = 760981.436 + 2700*69.78 = 949387.436
            
            total_value_account = 949387.436 + 10000 =959387.436
            
            return = 959387.436/1009503.808 - 1 = -0.04964455963696568
        
        """

        env = TradingEnv(data_source=data_source,
                         look_backward_window=2,
                         mode="non-rl",
                         starting_cash=starting_cash,
                         commission_multiplier=commission_multiplier,
                         min_commission=min_commission,
                         tax_multiplier=tax_multiplier)

        print('--------------------------------------------')
        #print("current context \n",Context.get_instance().__dict__)
        context = Context.get_instance()

        #stock account
        expect_market_value_stock = 0
        expect_cash_stock = starting_cash["STOCK"]
        expect_total_value_stock = expect_cash_stock + expect_market_value_stock

        #future account
        expect_market_value_future = 0
        expect_cash_future = starting_cash["FUTURE"]
        expect_total_value_future = expect_cash_future + expect_market_value_future
        expect_total_value_future = expect_total_value_future

        #portfolio
        expect_total_value_portfolio = expect_total_value_stock + expect_total_value_future

        trading_dts = context.get_available_trading_dts()
        first_trading_dt = trading_dts[0]
        order_book_id = order_book_ids[0]

        #
        target_weight = 0.5
        print(
            "------------the first trading date: {}--------------------------".
            format(env.trading_dt))
        to_submit_orders = order_target_weights({order_book_id: target_weight})

        submit_order = to_submit_orders[0]
        # ============================================================= #
        # step1: test trade correctness                                 #
        # ============================================================= #
        expect_deal_price1 = data_source.get_last_price(
            order_book_id=order_book_id, dt=first_trading_dt)
        print("fisrt date end price: {}".format(expect_deal_price1))
        expect_quantity1 = (STOCK_INIT_CASH *
                            target_weight) / expect_deal_price1
        expect_quantity1 = int(round(expect_quantity1 / 100) * 100)

        print((submit_order.quantity, expect_quantity1))

        expect_deal_money = expect_deal_price1 * expect_quantity1
        expect_commission_fee = expect_deal_money * commission_rate * commission_multiplier
        expect_tax = 0  # no tax rate when buy
        expect_transaction_cost = expect_commission_fee + expect_tax

        state, reward, is_done, info = env.step(action=to_submit_orders)

        true_order = context.tracker._orders[0]
        print(true_order)
        first_trade = context.tracker._trades[0]

        #first_trade = first_trade
        self.assertEqual(first=first_trade["order_book_id"],
                         second=order_book_id)
        self.assertEqual(first=first_trade["trading_datetime"],
                         second=first_trading_dt.strftime("%Y-%m-%d %H:%M:%S"))
        self.assertEqual(first=first_trade["last_price"],
                         second=expect_deal_price1)
        self.assertEqual(first=first_trade["commission"],
                         second=expect_commission_fee)
        self.assertEqual(first=first_trade["tax"], second=expect_tax)
        self.assertEqual(first=first_trade["transaction_cost"],
                         second=expect_transaction_cost)

        # =========================================== #
        # step2.1 test position                       #
        # step2.2 test account                        #
        # step2.3 test portfolio                      #
        # =========================================== #

        # portfolio and accounts change after trading
        #stock account
        expect_market_value_stock = expect_deal_money  #496192
        expect_cash_stock = starting_cash[
            "STOCK"] - expect_market_value_stock - expect_transaction_cost  #502448.2768
        expect_total_value_stock = expect_cash_stock + expect_market_value_stock

        portfolio = Context.get_instance().portfolio
        stock_account = portfolio.stock_account
        position1 = stock_account.get_position(order_book_id,
                                               POSITION_DIRECTION.LONG)
        print(expect_market_value_stock, position1.market_value)
        #pdb.set_trace()
        assert expect_market_value_stock == position1.market_value
        print(expect_market_value_stock, stock_account.market_value)
        print(expect_cash_stock, stock_account.total_cash)
        print(expect_total_value_stock, stock_account.total_value)

        self.assertEqual(expect_market_value_stock, position1.market_value)
        self.assertEqual(expect_market_value_stock, stock_account.market_value)
        self.assertEqual(expect_cash_stock, stock_account.total_cash)
        self.assertEqual(expect_total_value_stock, stock_account.total_value)

        # #future account
        expect_market_value_future = 0
        expect_cash_future = starting_cash["FUTURE"]
        expect_total_value_future = expect_cash_future + expect_market_value_future

        # #portfolio
        expect_cash_portfolio = expect_cash_stock + expect_cash_future
        expect_market_value = expect_market_value_stock + expect_market_value_future
        expect_total_value_portfolio_new = expect_total_value_stock + expect_total_value_future
        print(expect_cash_portfolio, portfolio.cash)
        print(expect_market_value, portfolio.market_value)
        print(expect_total_value_portfolio_new, portfolio.total_value)
        portfolio_record = Context.get_instance().tracker._total_portfolio[0]
        #print(portfolio_record)
        expect_reward = (expect_total_value_portfolio_new /
                         expect_total_value_portfolio) - 1
        print(expect_reward, reward, portfolio.daily_returns)
        #pdb.set_trace()
        self.assertEqual(expect_cash_portfolio, portfolio.cash)
        self.assertEqual(expect_market_value, portfolio.market_value)
        self.assertEqual(expect_total_value_portfolio_new,
                         portfolio.total_value)
        self.assertEqual(expect_reward, reward)

        # ============================================================== #
        # the next dt trade                                              #
        # ============================================================== #
        print(
            "------------the second trading date: {}--------------------------"
            .format(env.trading_dt))
        target_weight = 0.2

        second_trading_dt = trading_dts[1]
        print(second_trading_dt, env.trading_dt)
        self.assertEqual(second_trading_dt, env.trading_dt)

        to_submit_orders = order_target_weights({order_book_id: target_weight})
        order = to_submit_orders[0]
        #pdb.set_trace()

        expect_deal_price = data_source.get_last_price(
            order_book_id=order_book_id, dt=second_trading_dt)
        print("second date end price: {}".format(expect_deal_price))
        #here is the point: we need to get the updated account total value
        expect_deal_price = data_source.get_last_price(
            order_book_id=order_book_id, dt=second_trading_dt)  #69.78

        expect_market_value_stock = expect_quantity1 * expect_deal_price
        expect_cash_stock = expect_cash_stock
        expect_total_value_stock = expect_cash_stock + expect_market_value_stock

        expect_quantity2 = (expect_total_value_stock *
                            target_weight) / expect_deal_price
        expect_quantity2 = int(round(expect_quantity2 / 100) * 100)

        to_trade_quantity = abs(expect_quantity2 - expect_quantity1)
        #expect_quantity = true_order.quantity  #allow not 100 times
        #print((, expetrue_orderct_quantity))
        expect_deal_money = expect_deal_price * to_trade_quantity

        expect_commission_fee = expect_deal_money * commission_rate * commission_multiplier
        expect_tax = expect_deal_money * tax_rate * tax_multiplier  # no tax rate when buy, but charge when sell
        expect_transaction_cost = expect_commission_fee + expect_tax
        #pdb.set_trace()

        state, reward, is_done, info = env.step(action=to_submit_orders)

        true_order = context.tracker._orders[1]
        # if sell, allow the quantity is not 100 times
        print(true_order)
        second_trade = context.tracker._trades[1]
        print(second_trade["order_book_id"], order_book_id)
        print(second_trade["trading_datetime"],
              second_trading_dt.strftime("%Y-%m-%d %H:%M:%S"))
        print(second_trade["last_price"], expect_deal_price)
        print(second_trade["commission"], expect_commission_fee)
        print(second_trade["tax"], expect_tax)
        print(second_trade["transaction_cost"], expect_transaction_cost)
        self.assertEqual(first=second_trade["order_book_id"],
                         second=order_book_id)
        self.assertEqual(
            first=second_trade["trading_datetime"],
            second=second_trading_dt.strftime("%Y-%m-%d %H:%M:%S"))
        self.assertEqual(first=second_trade["last_price"],
                         second=expect_deal_price)
        self.assertEqual(first=second_trade["commission"],
                         second=expect_commission_fee)
        self.assertEqual(first=second_trade["tax"], second=expect_tax)
        self.assertEqual(first=second_trade["transaction_cost"],
                         second=expect_transaction_cost)
        #pdb.set_trace()

        # here is important and think why use settlement price rather the trade price
        # the special case. when sell at the end time of the trading time. the settlement price is equal to the trade price
        expect_cash_stock_settlement = expect_cash_stock + expect_deal_money - expect_transaction_cost
        expect_settlement_price = data_source.get_last_price(
            order_book_id=order_book_id, dt=second_trading_dt)

        position1 = stock_account.get_position(order_book_id,
                                               POSITION_DIRECTION.LONG)
        print(position1)
        #expect_remaining_market_value_stock_settlement = (first_trade["last_quantity"] - second_trade["last_quantity"]) * expect_settlement_price
        expect_market_value_stock_settlement = position1.quantity * expect_settlement_price
        expect_total_value_stock_settlement = expect_cash_stock_settlement + expect_market_value_stock_settlement

        portfolio = Context.get_instance().portfolio
        stock_account = portfolio.stock_account
        position1 = stock_account.get_position(order_book_id,
                                               POSITION_DIRECTION.LONG)
        #expect_reward = (expect_total_value_settlement - self.expect_total_value_settlement) / self.expect_total_value_settlement

        print(expect_market_value_stock_settlement, position1.market_value)
        print(expect_market_value_stock_settlement, stock_account.market_value)
        print(expect_cash_stock_settlement, stock_account.total_cash)
        print(expect_total_value_stock_settlement, stock_account.total_value)
        #pdb.set_trace()
        self.assertEqual(expect_market_value_stock_settlement,
                         position1.market_value)
        self.assertEqual(expect_market_value_stock_settlement,
                         stock_account.market_value)
        self.assertEqual(expect_cash_stock_settlement,
                         stock_account.total_cash)
        self.assertEqual(expect_total_value_stock_settlement,
                         stock_account.total_value)

        expect_cash_future_settlement = starting_cash["FUTURE"]
        expect_market_value_future_settlement = 0
        expect_total_value_future_settlement = expect_cash_future_settlement + expect_market_value_future_settlement

        expect_cash_portfolio_settlement = expect_cash_stock_settlement + expect_cash_future_settlement
        expect_market_value_portfolio_settlement = expect_market_value_stock_settlement + expect_market_value_future_settlement
        expect_total_value_settlement_portfolio_2 = expect_total_value_stock_settlement + expect_total_value_future_settlement

        #pdb.set_trace()
        print(expect_cash_portfolio_settlement, portfolio.cash)
        print(expect_market_value_portfolio_settlement, portfolio.market_value)
        print(expect_total_value_settlement_portfolio_2, portfolio.total_value)
        expect_reward = (expect_total_value_settlement_portfolio_2 /
                         expect_total_value_portfolio_new) - 1
        print(expect_reward, reward, portfolio.daily_returns)
        #pdb.set_trace()
        self.assertEqual(expect_cash_portfolio_settlement, portfolio.cash)
        self.assertEqual(expect_market_value_portfolio_settlement,
                         portfolio.market_value)
        self.assertEqual(expect_total_value_settlement_portfolio_2,
                         portfolio.total_value)
        self.assertEqual(expect_reward, reward)

        print(
            "------------the third trading date: {}--------------------------".
            format(env.trading_dt))
        third_trading_dt = trading_dts[2]
        print(second_trading_dt, env.trading_dt)

        target_weight = 0.0
        to_submit_orders = order_target_weights({order_book_id: target_weight})

        expect_deal_price = data_source.get_last_price(
            order_book_id=order_book_id, dt=third_trading_dt)
        print("third date end price: {}".format(expect_deal_price))  #72.5
        expect_quantity = 0  #allow not 100 times
        to_trade_quantity = expect_quantity2
        # #print((, expetrue_orderct_quantity))
        expect_deal_money = expect_deal_price * to_trade_quantity

        expect_commission_fee = expect_deal_money * commission_rate * commission_multiplier
        expect_tax = expect_deal_money * tax_rate * tax_multiplier  # no tax rate when buy
        expect_transaction_cost = expect_commission_fee + expect_tax

        state, reward, is_done, info = env.step(action=to_submit_orders)

        order = to_submit_orders[0]
        true_order = context.tracker._orders[2]
        # if sell, allow the quantity is not 100 times
        print(true_order)

        third_trade = context.tracker._trades[2]
        print(third_trade["order_book_id"], order_book_id)
        print(third_trade["trading_datetime"],
              second_trading_dt.strftime("%Y-%m-%d %H:%M:%S"))
        print(third_trade["last_price"], expect_deal_price)
        print(third_trade["commission"], expect_commission_fee)
        print(third_trade["tax"], expect_tax)
        print(third_trade["transaction_cost"], expect_transaction_cost)
        #pdb.set_trace()
        self.assertEqual(first=third_trade["order_book_id"],
                         second=order_book_id)
        self.assertEqual(first=third_trade["trading_datetime"],
                         second=third_trading_dt.strftime("%Y-%m-%d %H:%M:%S"))
        self.assertEqual(first=third_trade["last_price"],
                         second=expect_deal_price)
        self.assertEqual(first=third_trade["commission"],
                         second=expect_commission_fee)
        self.assertEqual(first=third_trade["tax"], second=expect_tax)
        self.assertEqual(first=third_trade["transaction_cost"],
                         second=expect_transaction_cost)

        # # here is important and think why use settlement price rather the trade price
        # # the special case. when sell at the end time of the trading time. the settlement price is equal to the trade price
        expect_cash_stock_settlement = expect_cash_stock_settlement + expect_deal_money - expect_transaction_cost
        expect_settlement_price = data_source.get_last_price(
            order_book_id=order_book_id, dt=third_trading_dt)

        position = stock_account.get_position(order_book_id,
                                              POSITION_DIRECTION.LONG)
        print(position)
        expect_market_value_stock_settlement = position.quantity * expect_settlement_price
        print("expect_market_value_stock_settlement: {}".format(
            expect_market_value_stock_settlement))
        #expect_remaining_market_value_stock_settlement = (first_trade["last_quantity"] - second_trade["last_quantity"]) * expect_settlement_price
        expect_total_value_stock_settlement = expect_cash_stock_settlement + expect_market_value_stock_settlement

        portfolio = Context.get_instance().portfolio
        stock_account = portfolio.stock_account
        position1 = stock_account.get_position(order_book_id,
                                               POSITION_DIRECTION.LONG)

        print(expect_market_value_stock_settlement, position1.market_value)
        print(expect_market_value_stock_settlement, stock_account.market_value)
        print("---------------------")
        print(expect_cash_stock_settlement, stock_account.total_cash)
        print(expect_total_value_stock_settlement, stock_account.total_value)
        #pdb.set_trace()
        self.assertEqual(expect_market_value_stock_settlement,
                         position1.market_value)
        self.assertEqual(expect_market_value_stock_settlement,
                         stock_account.market_value)
        self.assertEqual(expect_cash_stock_settlement,
                         stock_account.total_cash)
        self.assertEqual(expect_total_value_stock_settlement,
                         stock_account.total_value)

        expect_cash_future_settlement = starting_cash["FUTURE"]
        expect_market_value_future_settlement = 0
        expect_total_value_future_settlement = expect_cash_future_settlement + expect_market_value_future_settlement

        expect_cash_portfolio_settlement = expect_cash_stock_settlement + expect_cash_future_settlement
        expect_market_value_portfolio_settlement = expect_market_value_stock_settlement + expect_market_value_future_settlement
        expect_total_value_settlement_portfolio = expect_total_value_stock_settlement + expect_total_value_future_settlement

        print(expect_cash_portfolio_settlement, portfolio.cash)
        print(expect_market_value_portfolio_settlement, portfolio.market_value)
        print(expect_total_value_settlement_portfolio, portfolio.total_value)
        expect_reward = (expect_total_value_settlement_portfolio /
                         expect_total_value_settlement_portfolio_2) - 1
        print(expect_reward, reward, portfolio.daily_returns)
        print(portfolio.cash, portfolio.market_value, portfolio.total_value)
        #pdb.set_trace()
        self.assertEqual(expect_cash_portfolio_settlement, portfolio.cash)
        self.assertEqual(expect_market_value_portfolio_settlement,
                         portfolio.market_value)
        self.assertEqual(expect_total_value_settlement_portfolio,
                         portfolio.total_value)
        self.assertEqual(expect_reward, reward)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from sharpe.utils.mock_data import create_toy_feature
from sharpe.data.data_source import DataSource
from sharpe.environment import TradingEnv

feature_df, price_s = create_toy_feature(order_book_ids_number=2,
                                         feature_number=3,
                                         random_seed=111)
data_source = DataSource(feature_df=feature_df, price_s=price_s)

env = TradingEnv(data_source=data_source, look_backward_window=2)
print('--------------------------------------------')
from sharpe.core.context import Context
print("current context \n", Context.get_instance().__dict__)

from sharpe.mod.sys_account.api import order_target_weights
to_submit_orders = order_target_weights({"000001.XSHE": 0.5})

state, reward, is_done, info = env.step(action=to_submit_orders)
print(state, reward, is_done)
# to_submit_orders2 = order_target_portfolio({"000001.XSHE":0.2})
# state, reward, is_done, info = env.step(action=to_submit_orders2)
# print(state, reward, is_done)
Ejemplo n.º 22
0
 def test_portfolio_setup(self):
     portfolio = Context.get_instance().portfolio
     expected_total_value = sum(self.starting_cash.values())
     actual_total_value = portfolio.total_value
     self.assertEqual(actual_total_value, expected_total_value)
Ejemplo n.º 23
0
 def _on_before_trading(self, _):
     trading_date = Context.get_instance().trading_dt.date()
     for position in self._iter_pos():
         self._total_cash += position.before_trading(trading_date)
Ejemplo n.º 24
0
    def test_order_target_value(self):
        feature_df, price_s = create_toy_feature(order_book_ids_number=3,
                                                 feature_number=3,
                                                 random_seed=111)
        data_source = DataSource(feature_df=feature_df, price_s=price_s)

        all_order_book_ids = data_source.get_available_order_book_ids()
        print(all_order_book_ids)

        STOCK_INIT_CASH = 1000000

        env = TradingEnv(data_source=data_source,
                         look_backward_window=2,
                         mode="non-rl",
                         starting_cash={"STOCK": STOCK_INIT_CASH},
                         commission_multiplier=0,
                         min_commission=0,
                         tax_multiplier=0)

        state = env.reset()

        order_book_id = "000001.XSHE"
        print(
            "-----------------------current trading dt: {}-----------------------------------"
            .format(Context.get_instance().trading_dt))

        last_price = Context.get_instance().get_last_price(order_book_id)
        to_submit_orders1 = order_target_value(order_book_id, 500000)

        expect_quantity = int((500000 / last_price) / 100) * 100
        assert expect_quantity == to_submit_orders1.quantity
        self.assertEqual(first=expect_quantity,
                         second=to_submit_orders1.quantity)
        state, reward, is_done, info = env.step(action=[to_submit_orders1])

        current_positions0 = get_position(all_order_book_ids[0],
                                          POSITION_DIRECTION.LONG)

        print(
            "-----------------------current trading dt: {}-----------------------------------"
            .format(Context.get_instance().trading_dt))

        last_price = Context.get_instance().get_last_price(order_book_id)
        print(last_price)

        #current_positions2 = get_position(all_order_book_ids[0], POSITION_DIRECTION.LONG)

        to_submit_orders2 = order_target_value(order_book_id, 600000)

        gap_value = 600000 - current_positions0.market_value

        expect_quantity = int((gap_value / last_price) / 100) * 100

        assert expect_quantity == to_submit_orders2.quantity
        self.assertEqual(first=expect_quantity,
                         second=to_submit_orders2.quantity)

        state, reward, is_done, info = env.step(action=[to_submit_orders2])

        current_positions2 = get_position(all_order_book_ids[0],
                                          POSITION_DIRECTION.LONG)

        print(
            "-----------------------current trading dt: {}-----------------------------------"
            .format(Context.get_instance().trading_dt))

        last_price = Context.get_instance().get_last_price(order_book_id)
        print("price: {}".format(last_price))

        # to_submit_orders3 = order_value(order_book_id, 100000)
        to_submit_orders3 = order_target_value(order_book_id, 100000)
        gap_value = 100000 - current_positions2.market_value
        expect_quantity = abs(int((gap_value / last_price) / 100) * 100)
        self.assertEqual(first=expect_quantity,
                         second=to_submit_orders3.quantity)
        self.assertEqual(first=to_submit_orders3.side, second=SIDE.SELL)
        self.assertEqual(first=to_submit_orders3.position_effect,
                         second=POSITION_EFFECT.CLOSE)
Ejemplo n.º 25
0
    def setUp(self):
        #feature_df, price_s = create_toy_feature(order_book_ids_number=2, feature_number=3, start="2020-01-01", end="2020-01-11", random_seed=111)
        feature_df, price_s = create_toy_feature(order_book_ids_number=1,
                                                 feature_number=3,
                                                 random_seed=111)
        data_source = DataSource(feature_df=feature_df, price_s=price_s)
        #order_book_ids  = data_source.get_available_order_book_ids()

        self.data_source = DataSource(feature_df=feature_df, price_s=price_s)

        self.order_book_ids = self.data_source.get_available_order_book_ids()

        self.look_backward_window = 2

        self.starting_cash = {"STOCK": 1000000, "FUTURE": 10000}

        self.commission_rate = 0.0005
        self.tax_rate = 0.001

        self.commission_multiplier = 1
        self.min_commission = 5
        self.tax_multiplier = 1

        self.env = TradingEnv(data_source=self.data_source,
                              look_backward_window=self.look_backward_window,
                              mode="rl",
                              starting_cash=self.starting_cash,
                              commission_multiplier=self.commission_multiplier,
                              min_commission=self.min_commission,
                              tax_multiplier=self.tax_multiplier)

        context = Context.get_instance()

        #stock account
        expect_market_value_stock = 0
        expect_cash_stock = self.starting_cash["STOCK"]
        expect_total_value_stock = expect_cash_stock + expect_market_value_stock

        #future account
        expect_market_value_future = 0
        expect_cash_future = self.starting_cash["FUTURE"]
        expect_total_value_future = expect_cash_future + expect_market_value_future
        self.expect_total_value_future = expect_total_value_future
        #portfolio
        expect_total_value = expect_total_value_stock + expect_total_value_future

        self.trading_dts = context.get_available_trading_dts()
        first_trading_dt = self.trading_dts[0]
        self.order_book_id = self.order_book_ids[0]

        print("-------------first_trading_dt: {}----------".format(
            context.trading_dt))
        to_submit_orders = order_target_weights({self.order_book_id: 0.5})
        order = to_submit_orders[0]
        expect_deal_price = self.data_source.get_last_price(
            order_book_id=self.order_book_id, dt=first_trading_dt)
        expect_deal_money = expect_deal_price * order.quantity

        expect_commission_fee = expect_deal_money * self.commission_rate * self.commission_multiplier
        expect_tax = 0  # no tax rate when buy
        expect_transaction_cost = expect_commission_fee + expect_tax

        #pdb.set_trace()
        state, reward, is_done, info = self.env.step(action=to_submit_orders)

        first_trade = context.tracker._trades[0]

        #pdb.set_trace()
        self.first_trade = first_trade
        self.assertEqual(first=first_trade["order_book_id"],
                         second=self.order_book_id)
        self.assertEqual(first=first_trade["trading_datetime"],
                         second=first_trading_dt.strftime("%Y-%m-%d %H:%M:%S"))
        self.assertEqual(first=first_trade["last_price"],
                         second=expect_deal_price)
        self.assertEqual(first=first_trade["commission"],
                         second=expect_commission_fee)
        self.assertEqual(first=first_trade["tax"], second=expect_tax)
        self.assertEqual(first=first_trade["transaction_cost"],
                         second=expect_transaction_cost)

        # portfolio and accounts change after trading
        #stock account
        expect_market_value_stock = expect_deal_money
        expect_cash_stock = self.starting_cash[
            "STOCK"] - expect_market_value_stock - expect_transaction_cost  #502448.2768
        #expect_total_value_stock = expect_cash_stock + expect_market_value_stock

        #future account
        #expect_market_value_future = 0
        #expect_cash_future = self.starting_cash["FUTURE"]
        #expect_total_value_future = expect_cash_future + expect_market_value_future

        #portfolio
        #expect_total_value = expect_total_value_stock + expect_total_value_future

        # settlement on the next bar
        next_trading_dt = self.trading_dts[1]
        expect_settlement_price = self.data_source.get_last_price(
            order_book_id=self.order_book_id, dt=next_trading_dt)
        expect_market_value_stock_settlement = first_trade[
            "last_quantity"] * expect_settlement_price
        self.expect_cash_stock_settlement = expect_cash_stock
        self.expect_total_value_stock_settlement = self.expect_cash_stock_settlement + expect_market_value_stock_settlement

        self.expect_total_value_future_settlement = expect_total_value_future

        self.expect_total_value_settlement = self.expect_total_value_stock_settlement + self.expect_total_value_future_settlement

        expect_reward = (self.expect_total_value_settlement -
                         expect_total_value) / expect_total_value
        self.assertAlmostEqual(first=reward, second=expect_reward)
Ejemplo n.º 26
0
        info["profit_and_loss"] = tracker._portfolio_forward_bar_pnl[-1]

        if self._context.trading_dt == self.available_trading_dts[-1]:
            is_done = True
        else:
            is_done = False

        return reward, is_done, info


if __name__ == "__main__":
    from sharpe.utils.mock_data import create_toy_feature
    from sharpe.data.data_source import DataSource
    from sharpe.core.context import Context

    feature_df, price_s = create_toy_feature(order_book_ids_number=2,
                                             feature_number=3)
    data_source = DataSource(feature_df=feature_df, price_s=price_s)

    #
    context = Context(look_backward_window=2)
    context.set_data_source(data_source)

    #
    from sharpe.mod.event_source import SimulationEventSource
    default_event_source = SimulationEventSource()
    context.set_event_source(default_event_source)

    executor = Executor(context)
    executor.send(action=0)
Ejemplo n.º 27
0
 def prev_close(self):
     if not is_valid_price(self._prev_close):
         context = Context.get_instance()
         self._prev_close = context.data_source.get_prev_close(self._order_book_id, context.trading_dt)
     return self._prev_close
Ejemplo n.º 28
0
 def _open_orders(self):
     for order in Context.get_instance().broker.get_open_orders(self.order_book_id):
         if order.position_direction == self._direction:
             yield order
Ejemplo n.º 29
0
    def step(self, action):

        reward, is_done, info = self._executor.send(action)
        #pdb.set_trace()
        next_state = Context.get_instance().history_bars()
        return next_state, reward, is_done, info
Ejemplo n.º 30
0
def _get_account_position_ins(order_book_id):
    account = Context.get_instance().portfolio.accounts[
        DEFAULT_ACCOUNT_TYPE.STOCK]
    position = account.get_position(order_book_id, POSITION_DIRECTION.LONG)
    return account, position