コード例 #1
0
 def concurrent_engine_quotes(num=4):
     engine = Engine(best_ip=True, thread_num=num)
     engine.connect()
     engine.stock_list.index.tolist()
     now = datetime.now()
     engine.stock_quotes()
     return (datetime.now() - now).total_seconds()
コード例 #2
0
 def original_engine_quotes():
     engine = Engine(best_ip=True)
     engine.connect()
     engine.stock_list.index.tolist()
     now = datetime.now()
     engine.stock_quotes()
     return (datetime.now() - now).total_seconds()
コード例 #3
0
ファイル: test_engine.py プロジェクト: htq310542/tdx
def transactions():
    eg = Engine(best_ip=True)
    eg.connect()
    m1 = eg.get_security_bars('000001', '1m')
    df = eg.time_and_price('000001')
    ohlcv = df.price.resample('1 Min', label='right', closed='left').ohlc()
    ohlcv['volume'] = df.vol.resample('1 Min', label='right',
                                      closed='left').sum()
コード例 #4
0
def tdx_bundle(assets,
               ingest_minute,  # whether to ingest minute data, default False
               environ,
               asset_db_writer,
               minute_bar_writer,
               daily_bar_writer,
               adjustment_writer,
               calendar,
               start_session,
               end_session,
               cache,
               show_progress,
               output_dir):
    eg = Engine(auto_retry=True, multithread=True, best_ip=True, thread_num=8)
    eg.connect()

    symbols = fetch_symbols(eg, assets)
    metas = []

    def gen_symbols_data(symbol_map, freq='1d'):
        for index, symbol in symbol_map.iteritems():
            data = reindex_to_calendar(
                calendar,
                fetch_single_equity(eg, symbol, freq),
                freq=freq,
            )
            if freq == '1d':
                metas.append(get_meta_from_bars(data))
            yield int(symbol), data

    symbol_map = symbols.symbol

    assets = set([int(s) for s in symbol_map])
    daily_bar_writer.write(gen_symbols_data(symbol_map, freq="1d"), assets=assets, show_progress=show_progress)

    if ingest_minute:
        with click.progressbar(gen_symbols_data(symbol_map, freq="1m"),
                               label="Merging minute equity files:",
                               length=len(assets),
                               item_show_func=lambda e: e if e is None else str(e[0]),
                               ) as bar:
            minute_bar_writer.write(bar, show_progress=False)

    symbols = pd.concat([symbols, pd.DataFrame(data=metas)], axis=1)
    splits, dividends = fetch_splits_and_dividends(eg, symbols)
    symbols.set_index('symbol', drop=False, inplace=True)
    asset_db_writer.write(symbols)
    adjustment_writer.write(
        splits=splits,
        dividends=dividends
    )

    eg.exit()
コード例 #5
0
ファイル: test_ingest.py プロジェクト: yucanbin/cn_zipline
def test_data():
    eg = Engine(auto_retry=True, multithread=True, thread_num=8)
    with eg.connect():

        symbols = fetch_symbols(eg)
        symbols = symbols[:5]
        metas = []

        def gen_symbols_data(symbol_map, freq='1d'):
            for index, symbol in symbol_map.iteritems():
                data = fetch_single_equity(eg, symbol, freq)

                if freq == '1d':
                    metas.append(get_meta_from_bars(data))

                assert data is not None
                yield int(symbol), data

        symbol_map = symbols.symbol

        assets = set([int(s) for s in symbol_map])
        gen_symbols_data(symbol_map, freq="1d")
        gen_symbols_data(symbol_map, freq="1m")

        symbols = pd.concat([symbols, pd.DataFrame(data=metas)], axis=1)
        splits, dividends = fetch_splits_and_dividends(eg, symbols)
        symbols.set_index('symbol', drop=False, inplace=True)

        assert symbols is not None
        assert splits is not None
        assert dividends is not None
コード例 #6
0
    def test_security_list():
        engine = Engine(best_ip=True)
        engine.connect()
        code = engine.stock_list.index.tolist()
        api = TdxHq_API()
        api.connect()
        best_ip = engine.best_ip

        print("security list: ({},{})".format(concurrent_api(2),
                                              original_api()))

        print("concurrent quotes ({},{})".format(
            concurrent_quotes(code, best_ip, 2),
            original_quotes(code, best_ip)))

        print("concurrent engine quotes ({},{})".format(
            concurrent_engine_quotes(2), original_engine_quotes()))
コード例 #7
0
def test_transaction():
    engine = Engine(best_ip=True, thread_num=1)
    with engine.connect():
        df = engine.get_k_data('000001', '20170601', '20171231', '1m')

        df = engine.get_security_bars(['000001', '000521'],
                                      '1d',
                                      start=pd.to_datetime('20180102'))
コード例 #8
0
ファイル: test_engine.py プロジェクト: yuzhucu/tdx
def engine_func(best_ip, thread_num):
    engine = Engine(best_ip=best_ip, thread_num=thread_num)

    with engine.connect():
        assert engine.best_ip is not None
        assert engine.gbbq is not None
        assert engine.security_list is not None
        assert engine.stock_quotes() is not None
        assert engine.customer_block is not None
        assert engine.quotes('000001') is not None
        assert engine.get_security_bars('000001', '1m') is not None
        assert engine.get_security_bars('000001', '1d') is not None
        assert engine.get_security_bars('000300', '1m', index=True) is not None
        assert engine.get_security_bars('000300', '1d', index=True) is not None
        assert engine.concept is not None
        assert engine.fengge is not None
        assert engine.index is not None
        assert engine.stock_list is not None
コード例 #9
0
class TdxCatsBroker(TdxShipaneBroker):
    """
    中信Cats系统CSV下单模块封装
    """

    def __init__(self, cats_client=None):
        """

        :param cat_client:
        :type cat_client: CatsTrade
        """
        self._shipane_client = cats_client
        self._orders = {}
        self.currency = 'RMB'
        self._subscribed_assets = []
        self._bars = {}
        self._bars_update_dt = None
        self._bars_update_interval = pd.tslib.Timedelta('5 S')
        self._mkt_client = Engine(auto_retry=True, best_ip=True)
        self._mkt_client.connect()
        # super(TdxShipaneBroker, self).__init__(tdx_uri, account_id)

    def tdx_order_to_zipline_order(self, order):
        """
        status
        0	已报
        1	部分成交
        2	全部成交
        3	部分撤单
        4	全部撤单
        5	交易所拒单
        6	柜台未接受

        :param order:
        :return:
        """
        if order.status == "3" or '4' == order.status:
            zp_status = ZP_ORDER_STATUS.CANCELLED
        elif order.status == "0":
            zp_status = ZP_ORDER_STATUS.OPEN
        elif order.status == "1":
            zp_status = ZP_ORDER_STATUS.FILLED
        elif order.status == "2":
            zp_status = ZP_ORDER_STATUS.HELD
        elif order.status == "5" or order.status == "6":
            zp_status = ZP_ORDER_STATUS.REJECTED


        zp_order_id = self._tdx_to_zp_order_id(order.order_id)

        od = ZPOrder(
            dt=order.dt,
            asset=symbol(order.symbol),
            amount=order.amount,
            filled=order.filled,
            stop=None,
            limit=order.price,  # TODO 市价单和限价单
            id=zp_order_id,
        )
        od.broker_order_id = order.order_id
        od.status = zp_status

        return od
コード例 #10
0
ファイル: tdx_bundle.py プロジェクト: xujun05/nzl
        pass
    calendar = get_calendar('SHSZ')
    if start:
        if not calendar.is_session(start):
            start = calendar.all_sessions[searchsorted(calendar.all_sessions,
                                                       start)]
    bundles.register('tdx',
                     partial(tdx_bundle, assets, minute, fundamental),
                     'SHSZ',
                     start,
                     end,
                     minutes_per_day=240)


bundles.register('tdx',
                 partial(tdx_bundle, None, False, False),
                 minutes_per_day=240)

if __name__ == '__main__':
    eg = Engine(auto_retry=True, multithread=True, thread_num=8)
    with eg.connect():
        symbols = fetch_symbols(eg)
        symbols = symbols[:3]
        data = []
        metas = []
        for symbol in symbols.symbol:
            data.append((int(symbol), fetch_single_equity(eg, symbol)))
            metas.append(get_meta_from_bars(data[-1][1]))
        symbols = pd.concat([symbols, pd.DataFrame(data=metas)], axis=1)
        splits, dividends = fetch_splits_and_dividends(eg, symbols)
コード例 #11
0
ファイル: tdx_broker.py プロジェクト: xujun05/nzl
class TdxBroker(Broker):
    def __init__(self, tdx_uri, account_id=None):

        self._orders = {}
        if tdx_uri.startswith('tcp'):
            self._client = zerorpc.Client()
            self._client.connect(tdx_uri)
        elif platform.architecture()[0] == '32bit':
            self._client = TdxClient(tdx_uri)
            self._client.login()
        else:
            raise Exception(
                "please use 32bit python to use local client directly, or use tcp client"
            )
        self.currency = 'RMB'
        self._subscribed_assets = []
        self._bars = {}
        self._bars_update_dt = None
        self._bars_update_interval = pd.tslib.Timedelta('5 S')
        self._mkt_client = Engine(auto_retry=True, best_ip=True)
        self._mkt_client.connect()

        super(TdxBroker, self).__init__()

    def subscribe_to_market_data(self, asset):
        # TODO fix me subcribe_to_market_data
        if asset not in self.subscribed_assets:
            # remove str() cast to have a fun debugging journey
            # self._client.subscribe_to_market_data(str(asset.symbol))
            self._subscribed_assets.append(asset)
            self._bars_update_dt = None

    def _update_bars(self):
        now = pd.to_datetime('now')
        if self._bars_update_dt and (now - self._bars_update_dt <
                                     self._bars_update_interval):
            return
        for code in self.subscribed_assets:
            bars = self._mkt_client.time_and_price(code.symbol)
            bars.index = bars.index.tz_localize('Asia/Shanghai').tz_convert(
                'UTC')
            self._bars[code.symbol] = bars

        self._bars_update_dt = now

    @property
    def subscribed_assets(self):
        return self._subscribed_assets

    @property
    def positions(self):
        now = datetime.datetime.now()
        z_positions = protocol.Positions()
        for pos in self._client.positions():
            if isinstance(pos, list):
                pos = TdxPosition(*pos)
            sid = pos.sid
            available = pos.available
            z_position = protocol.Position(symbol(sid))
            z_position.amount = pos.amount
            z_position.cost_basis = pos.cost_basis
            z_position.last_sale_price = pos.last_sale_price
            z_position.last_sale_date = now
            z_positions[symbol(sid)] = z_position

        return z_positions

    @property
    def portfolio(self):
        z_portfolio = protocol.Portfolio()
        pfo = self._client.portfolio()
        if isinstance(pfo, list):
            pfo = TdxPortfolio(*pfo)
        z_portfolio.capital_used = None  # TODO
        z_portfolio.starting_cash = None
        z_portfolio.portfolio_value = pfo.portfolio_value
        z_portfolio.pnl = None
        z_portfolio.returns = None
        z_portfolio.cash = pfo.cash
        z_portfolio.start_date = None
        z_portfolio.positions = self.positions
        z_portfolio.positions_value = pfo.positions_value
        z_portfolio.position_exposure = z_portfolio.positions_value / (
            z_portfolio.positions_value + z_portfolio.cash)

        return z_portfolio

    @property
    def account(self):
        z_account = protocol.Account()
        z_account.settled_cash = self.portfolio.cash
        z_account.accrued_interest = None
        z_account.buying_power = self.portfolio.portfolio_value
        z_account.equity_with_loan = self.portfolio.portfolio_value
        z_account.total_positions_value = self.portfolio.positions_value
        z_account.total_positions_exposure = z_account.total_positions_value / (
            z_account.total_positions_value + z_account.settled_cash)

        return z_account

    @property
    def time_skew(self):
        return pd.Timedelta('1 S')

    def order(self, asset, amount, style):
        code = asset.symbol

        if amount > 0:
            action = BUY
        else:
            action = SELL

        is_busy = (amount > 0)
        if isinstance(style, MarketOrder):
            order_type = FIVE_LEVEL_MARKET_ORDER
            price = 0.0
        elif isinstance(style, LimitOrder):
            order_type = LIMIT_CHARGE
            price = style.get_limit_price(is_busy)
        elif isinstance(style, StopOrder):
            raise Exception("stop order is not supported")
        elif isinstance(style, StopLimitOrder):
            raise Exception("stop limit order is not supported")

        data, err = self._client.order(code, abs(amount), price, action,
                                       order_type)
        if isinstance(data, list):
            data = OrderRt(*data)
        order_id = str(data.order_id)
        zp_order = self._get_or_create_zp_order(order_id)

        log.info("Placing order-{order_id}: "
                 "{action} {qty} {symbol} with {order_type}, price = {price}".
                 format(order_id=order_id,
                        action=action,
                        qty=amount,
                        symbol=code,
                        order_type=order_type,
                        price=price))

        return zp_order

    @property
    def orders(self):
        self._update_orders()
        return self._orders

    def _get_or_create_zp_order(self, order_id, order=None):
        zp_order_id = self._tdx_to_zp_order_id(order_id)
        if zp_order_id in self._orders:
            return self._orders[zp_order_id]

        if not order:
            order = self._client.orders()[order_id]

        if isinstance(order,
                      list):  # handle rpc response for namedtuple object
            order = TdxOrder(*order)
        self._orders[zp_order_id] = self.tdx_order_to_zipline_order(order)
        return self._orders[zp_order_id]

    # amount 可正数可负数
    def _create_zp_order(self, order_id, asset, price, amount, order_type):
        zp_order_id = self._tdx_to_zp_order_id(order_id)
        if zp_order_id in self._orders:
            return self._orders[zp_order_id]

        dt = pd.to_datetime("now", utc=True)
        self._orders[zp_order_id] = ZPOrder(
            dt=dt,
            asset=asset,
            amount=amount,
            stop=None,
            limit=price if order_type is LIMIT_CHARGE else None,
            id=zp_order_id,
            broker_order_id=order_id)

        return self._orders[zp_order_id]

    def _tdx_to_zp_order_id(self, order_id):
        return "TDX-{date}-{account_id}-{order_id}".format(
            date=str(pd.to_datetime('today').date()),
            account_id=self._client.account_id(),
            order_id=order_id)

    def tdx_order_to_zipline_order(self, order):
        if order.status == '已撤':
            zp_status = ZP_ORDER_STATUS.CANCELLED
        elif order.filled == 0:
            zp_status = ZP_ORDER_STATUS.OPEN
        else:
            zp_status = ZP_ORDER_STATUS.FILLED

        zp_order_id = self._tdx_to_zp_order_id(order.order_id)

        od = ZPOrder(
            dt=pd.to_datetime(order.dt),
            asset=symbol(order.symbol),
            amount=order.amount,
            filled=order.filled,
            stop=None,
            limit=order.price,  # TODO 市价单和限价单
            id=zp_order_id,
        )
        od.broker_order_id = order.order_id
        od.status = zp_status

        return od

    def _update_orders(self):
        ods = self._client.orders()
        for tdx_order_id, tdx_order in iteritems(ods):
            if isinstance(tdx_order,
                          list):  # handle rpc response for namedtuple object
                tdx_order = TdxOrder(*tdx_order)
            zp_order_id = self._tdx_to_zp_order_id(tdx_order_id)
            self._orders[zp_order_id] = self.tdx_order_to_zipline_order(
                tdx_order)

    def _tdx_transaction_to_zipline(self, transaction):
        return ZPTransaction(
            asset=symbol(transaction.asset),
            amount=transaction.amount,
            dt=pd.to_datetime(
                transaction.dt).tz_localize('Asia/Shanghai').tz_convert('UTC'),
            price=transaction.price,
            order_id=self._tdx_to_zp_order_id(transaction.order_id),
            commission=transaction.commission,
        )

    @property
    def transactions(self):
        t = self._client.transactions()
        rt = {}
        for exec_id, transaction in t.items():
            try:
                if isinstance(
                        transaction,
                        list):  # handle rpc response for namedtuple object
                    transaction = TdxTransaction(*transaction)
                rt[exec_id] = self._tdx_transaction_to_zipline(transaction)
            except SymbolNotFound as e:
                log.warning(e.message)

        return rt

    def cancel_order(self, order_id):
        if order_id not in self.orders:  # order become transaction, can't cancel
            return
        tdx_order_id = self.orders[order_id].broker_order_id
        broker_id = self._client.get_stock_type("{:6d}".format(
            self.orders[order_id].asset.sid))
        self._client.cancel_orders(broker_id, tdx_order_id)

    def get_last_traded_dt(self, asset):
        self.subscribe_to_market_data(asset)
        self._update_bars()

        return self._bars[str(asset.symbol)].index[-1]

    def get_spot_value(self, assets, field, dt, data_frequency):
        symbol = str(assets.symbol)
        self.subscribe_to_market_data(assets)
        self._update_bars()

        bars = self._bars[symbol]
        last_event_time = bars.index[-1]

        minute_start = (last_event_time - pd.Timedelta('1 min')) \
            .time()
        minute_end = last_event_time.time()

        if bars.empty:
            return pd.NaT if field == 'last_traded' else np.NaN
        else:
            if field == 'price':
                return bars.price.iloc[-1]
            elif field == 'last_traded':
                return last_event_time or pd.NaT

            minute_df = bars.between_time(minute_start,
                                          minute_end,
                                          include_start=True,
                                          include_end=True)

            if minute_df.empty:
                return np.NaN
            else:
                if field == 'open':
                    return minute_df.price.iloc[0]
                elif field == 'close':
                    return minute_df.price.iloc[-1]
                elif field == 'high':
                    return minute_df.price.max()
                elif field == 'low':
                    return minute_df.price.min()
                elif field == 'volume':
                    return minute_df.vol.sum()

    def get_realtime_bars(self, assets, frequency):
        if frequency == '1m':
            resample_freq = 'Min'
        elif frequency == '1d':
            resample_freq = '24 H'
        else:
            raise ValueError("Invalid frequency specified: %s" % frequency)

        df = pd.DataFrame()

        for asset in assets:
            symbol = str(asset.symbol)
            self.subscribe_to_market_data(asset)
            self._update_bars()

            trade_prices = self._bars[symbol]['price']
            trade_sizes = self._bars[symbol]['vol']
            ohlcv = trade_prices.resample(resample_freq,
                                          label='right',
                                          closed='left').ohlc()
            ohlcv['volume'] = trade_sizes.resample(resample_freq,
                                                   label='right',
                                                   closed='left').sum()

            ohlcv.columns = pd.MultiIndex.from_product([[
                asset,
            ], ohlcv.columns])
            df = pd.concat([df, ohlcv], axis=1)

        return df
コード例 #12
0
ファイル: tdx_bundle.py プロジェクト: huangzhengyong/zipline
    eg.exit()


def register_tdx(assets=None, minute=False, start=None, fundamental=False, end=None):
    try:
        bundles.unregister('tdx')
    except bundles.UnknownBundle:
        pass
    calendar = get_calendar('SHSZ')
    if start:
        if not calendar.is_session(start):
            start = calendar.all_sessions[searchsorted(calendar.all_sessions, start)]
    bundles.register('tdx', partial(tdx_bundle, assets, minute, fundamental), 'SHSZ', start, end,
                     minutes_per_day=240)


bundles.register('tdx', partial(tdx_bundle, None, False, False), minutes_per_day=240)

if __name__ == '__main__':
    eg = Engine(auto_retry=True, multithread=True, thread_num=8)
    with eg.connect():
        symbols = fetch_symbols(eg)
        symbols = symbols[:3]
        data = []
        metas = []
        for symbol in symbols.symbol:
            data.append((int(symbol), fetch_single_equity(eg, symbol)))
            metas.append(get_meta_from_bars(data[-1][1]))
        symbols = pd.concat([symbols, pd.DataFrame(data=metas)], axis=1)
        splits, dividends = fetch_splits_and_dividends(eg, symbols)
コード例 #13
0
ファイル: test_engine.py プロジェクト: nopain1573/tdx-1
def transactions():
    eg = Engine(best_ip=True, auto_retry=True)
    eg.connect()
    m1 = eg.get_k_data('000001', '20170101', '20180101', '1m')
コード例 #14
0
ファイル: main.py プロジェクト: nopain1573/tdx-1
def main():
    logbook.StderrHandler().push_application()
    engine = Engine(best_ip=True, thread_num=1)
    with engine.connect():
        engine.get_k_data('000002', '20100921', '20100930', '1m')
コード例 #15
0
ファイル: cn_loader.py プロジェクト: huangzhengyong/zipline
def ensure_benchmark_data(symbol, first_date, last_date, now, trading_day):
    """
    Ensure we have benchmark data for `symbol` from `first_date` to `last_date`

    Parameters
    ----------
    symbol : str
        The symbol for the benchmark to load.
    first_date : pd.Timestamp
        First required date for the cache.
    last_date : pd.Timestamp
        Last required date for the cache.
    now : pd.Timestamp
        The current time.  This is used to prevent repeated attempts to
        re-download data that isn't available due to scheduling quirks or other
        failures.
    trading_day : pd.CustomBusinessDay
        A trading day delta.  Used to find the day before first_date so we can
        get the close of the day prior to first_date.

    We attempt to download data unless we already have data stored at the data
    cache for `symbol` whose first entry is before or on `first_date` and whose
    last entry is on or after `last_date`.

    If we perform a download and the cache criteria are not satisfied, we wait
    at least one hour before attempting a redownload.  This is determined by
    comparing the current time to the result of os.path.getmtime on the cache
    path.
    """
    path = get_data_filepath(get_benchmark_filename(symbol))

    # If the path does not exist, it means the first download has not happened
    # yet, so don't try to read from 'path'.
    if os.path.exists(path):
        try:
            data = pd.Series.from_csv(path).tz_localize('UTC')
            if has_data_for_dates(data, first_date, last_date):
                return data

            # Don't re-download if we've successfully downloaded and written a
            # file in the last hour.
            last_download_time = last_modified_time(path)
            if (now - last_download_time) <= ONE_HOUR:
                logger.warn(
                    "Refusing to download new benchmark data because a "
                    "download succeeded at %s." % last_download_time
                )
                return data

        except (OSError, IOError, ValueError) as e:
            # These can all be raised by various versions of pandas on various
            # classes of malformed input.  Treat them all as cache misses.
            logger.info(
                "Loading data for {path} failed with error [{error}].".format(
                    path=path, error=e,
                )
            )
    logger.info(
        "Cache at {path} does not have data from {start} to {end}.\n"
        "Downloading benchmark data for '{symbol}'.",
        start=first_date,
        end=last_date,
        symbol=symbol,
        path=path,
    )

    engine = Engine(auto_retry=True, multithread=True, thread_num=8, best_ip=True)
    engine.connect()
    data = engine.get_security_bars(symbol, '1d',index=True)
    data = data['close'].sort_index().tz_localize('UTC').pct_change(1).iloc[1:]
    data.index = data.index.normalize() # change datetime at 15:00 to midnight
    data.to_csv(path)
    return data
コード例 #16
0
    print(grouped.sort_values('up_limit', ascending=False))


def minute_time_data():
    stock_list = engine.stock_list.index.tolist()

    now = datetime.datetime.now()

    for stock in stock_list:
        fs = engine.api.to_df(
            engine.api.get_minute_time_data(stock[0], stock[1]))
        # print(fs)

    print((datetime.datetime.now() - now).total_seconds())


def quotes():
    start_dt = datetime.datetime.now()
    quote = engine.stock_quotes()
    print(datetime.datetime.now() - start_dt).total_seconds()
    process_quotes(quote)


if __name__ == '__main__':
    engine = Engine(best_ip=True)
    with engine.connect():

        print(
            engine.get_security_bars('002920', '1d',
                                     pd.to_datetime('20170701')))
コード例 #17
0
ファイル: tdx_broker.py プロジェクト: huangzhengyong/zipline
class TdxBroker(Broker):
    def __init__(self, tdx_uri, account_id=None):

        self._orders = {}
        if tdx_uri.startswith('tcp'):
            self._client = zerorpc.Client()
            self._client.connect(tdx_uri)
        elif platform.architecture()[0] == '32bit':
            self._client = TdxClient(tdx_uri)
            self._client.login()
        else:
            raise Exception("please use 32bit python to use local client directly, or use tcp client")
        self.currency = 'RMB'
        self._subscribed_assets = []
        self._bars = {}
        self._bars_update_dt = None
        self._bars_update_interval = pd.tslib.Timedelta('5 S')
        self._mkt_client = Engine(auto_retry=True, best_ip=True)
        self._mkt_client.connect()

        super(TdxBroker, self).__init__()

    def subscribe_to_market_data(self, asset):
        # TODO fix me subcribe_to_market_data
        if asset not in self.subscribed_assets:
            # remove str() cast to have a fun debugging journey
            # self._client.subscribe_to_market_data(str(asset.symbol))
            self._subscribed_assets.append(asset)
            self._bars_update_dt = None

    def _update_bars(self):
        now = pd.to_datetime('now')
        if self._bars_update_dt and (now - self._bars_update_dt < self._bars_update_interval):
            return
        for code in self.subscribed_assets:
            bars = self._mkt_client.time_and_price(code.symbol)
            if bars.empty:
                return
            bars.index = bars.index.tz_localize('Asia/Shanghai').tz_convert('UTC')
            self._bars[code.symbol] = bars

        self._bars_update_dt = now

    @property
    def subscribed_assets(self):
        return self._subscribed_assets

    def is_alive(self):
        return True

    @property
    def positions(self):
        now = datetime.datetime.now()
        z_positions = protocol.Positions()
        for pos in self._client.positions():
            if isinstance(pos, list):
                pos = TdxPosition(*pos)
            sid = pos.sid
            available = pos.available
            z_position = protocol.Position(symbol(sid))
            z_position.amount = pos.amount
            z_position.cost_basis = pos.cost_basis
            z_position.last_sale_price = pos.last_sale_price
            z_position.last_sale_date = now
            z_positions[symbol(sid)] = z_position

        return z_positions

    @property
    def portfolio(self):
        z_portfolio = protocol.Portfolio()
        pfo = self._client.portfolio()
        if isinstance(pfo, list):
            pfo = TdxPortfolio(*pfo)
        z_portfolio.capital_used = None  # TODO
        z_portfolio.starting_cash = None
        z_portfolio.portfolio_value = pfo.portfolio_value
        z_portfolio.pnl = None
        z_portfolio.returns = None
        z_portfolio.cash = pfo.cash
        z_portfolio.start_date = None
        z_portfolio.positions = self.positions
        z_portfolio.positions_value = pfo.positions_value
        z_portfolio.position_exposure = z_portfolio.positions_value / (z_portfolio.positions_value + z_portfolio.cash)

        return z_portfolio

    @property
    def account(self):
        z_account = protocol.Account()
        z_account.settled_cash = self.portfolio.cash
        z_account.accrued_interest = None
        z_account.buying_power = self.portfolio.portfolio_value
        z_account.equity_with_loan = self.portfolio.portfolio_value
        z_account.total_positions_value = self.portfolio.positions_value
        z_account.total_positions_exposure = z_account.total_positions_value / (
            z_account.total_positions_value + z_account.settled_cash)

        return z_account

    @property
    def time_skew(self):
        return pd.Timedelta('1 S')

    def order(self, asset, amount, style):
        code = asset.symbol

        if amount > 0:
            action = BUY
        else:
            action = SELL

        is_busy = (amount > 0)
        if isinstance(style, MarketOrder):
            order_type = FIVE_LEVEL_MARKET_ORDER
            price = 0.0
        elif isinstance(style, LimitOrder):
            order_type = LIMIT_CHARGE
            price = style.get_limit_price(is_busy)
        elif isinstance(style, StopOrder):
            raise Exception("stop order is not supported")
        elif isinstance(style, StopLimitOrder):
            raise Exception("stop limit order is not supported")

        data, err = self._client.order(code, abs(amount), price, action, order_type)
        if isinstance(data,list):
            data = OrderRt(*data)
        order_id = str(data.order_id)
        zp_order = self._get_or_create_zp_order(order_id)

        log.info("Placing order-{order_id}: "
                 "{action} {qty} {symbol} with {order_type}, price = {price}".format(
            order_id=order_id,
            action=action,
            qty=amount,
            symbol=code,
            order_type=order_type,
            price=price
        ))

        return zp_order

    @property
    def orders(self):
        self._update_orders()
        return self._orders

    def _get_or_create_zp_order(self, order_id, order=None):
        zp_order_id = self._tdx_to_zp_order_id(order_id)
        if zp_order_id in self._orders:
            return self._orders[zp_order_id]

        if not order:
            order = self._client.orders()[order_id]

        if isinstance(order, list):  # handle rpc response for namedtuple object
            order = TdxOrder(*order)
        self._orders[zp_order_id] = self.tdx_order_to_zipline_order(order)
        return self._orders[zp_order_id]

    # amount 可正数可负数
    def _create_zp_order(self, order_id, asset, price, amount, order_type):
        zp_order_id = self._tdx_to_zp_order_id(order_id)
        if zp_order_id in self._orders:
            return self._orders[zp_order_id]

        dt = pd.to_datetime("now", utc=True)
        self._orders[zp_order_id] = ZPOrder(
            dt=dt,
            asset=asset,
            amount=amount,
            stop=None,
            limit=price if order_type is LIMIT_CHARGE else None,
            id=zp_order_id,
            broker_order_id=order_id
        )

        return self._orders[zp_order_id]

    def _tdx_to_zp_order_id(self, order_id):
        return "TDX-{date}-{account_id}-{order_id}".format(
            date=str(pd.to_datetime('today').date()),
            account_id=self._client.account_id(),
            order_id=order_id
        )

    def tdx_order_to_zipline_order(self, order):
        if order.status == '已撤':
            zp_status = ZP_ORDER_STATUS.CANCELLED
        elif order.filled == 0:
            zp_status = ZP_ORDER_STATUS.OPEN
        else:
            zp_status = ZP_ORDER_STATUS.FILLED

        zp_order_id = self._tdx_to_zp_order_id(order.order_id)

        od = ZPOrder(
            dt=pd.to_datetime(order.dt),
            asset=symbol(order.symbol),
            amount=order.amount,
            filled=order.filled,
            stop=None,
            limit=order.price,  # TODO 市价单和限价单
            id=zp_order_id,
        )
        od.broker_order_id = order.order_id
        od.status = zp_status

        return od

    def _update_orders(self):
        ods = self._client.orders()
        for tdx_order_id, tdx_order in iteritems(ods):
            if isinstance(tdx_order, list):  # handle rpc response for namedtuple object
                tdx_order = TdxOrder(*tdx_order)
            zp_order_id = self._tdx_to_zp_order_id(tdx_order_id)
            self._orders[zp_order_id] = self.tdx_order_to_zipline_order(tdx_order)

    def _tdx_transaction_to_zipline(self, transaction):
        return ZPTransaction(
            asset=symbol(transaction.asset),
            amount=transaction.amount,
            dt=pd.to_datetime(transaction.dt).tz_localize('Asia/Shanghai').tz_convert('UTC'),
            price=transaction.price,
            order_id=self._tdx_to_zp_order_id(transaction.order_id),
            commission=transaction.commission,
        )

    @property
    def transactions(self):
        t = self._client.transactions()
        rt = {}
        for exec_id, transaction in t.items():
            try:
                if isinstance(transaction, list):  # handle rpc response for namedtuple object
                    transaction = TdxTransaction(*transaction)
                rt[exec_id] = self._tdx_transaction_to_zipline(transaction)
            except SymbolNotFound as e:
                log.warning(e.message)

        return rt

    def cancel_order(self, order_id):
        if order_id not in self.orders:  # order become transaction, can't cancel
            return
        tdx_order_id = self.orders[order_id].broker_order_id
        broker_id = self._client.get_stock_type("{:6d}".format(self.orders[order_id].asset.sid))
        self._client.cancel_orders(broker_id, tdx_order_id)

    def get_last_traded_dt(self, asset):
        self.subscribe_to_market_data(asset)
        self._update_bars()

        return self._bars[str(asset.symbol)].index[-1]

    def get_spot_value(self, assets, field, dt, data_frequency):
        symbol = str(assets.symbol)
        self.subscribe_to_market_data(assets)
        self._update_bars()
        if symbol not in self._bars:
            return pd.NaT if field == 'last_traded' else np.NaN
        bars = self._bars[symbol]
        last_event_time = bars.index[-1]

        minute_start = (last_event_time - pd.Timedelta('1 min')) \
            .time()
        minute_end = last_event_time.time()

        if bars.empty:
            return pd.NaT if field == 'last_traded' else np.NaN
        else:
            if field == 'price':
                return bars.price.iloc[-1]
            elif field == 'last_traded':
                return last_event_time or pd.NaT

            minute_df = bars.between_time(minute_start, minute_end,
                                          include_start=True, include_end=True)

            if minute_df.empty:
                return np.NaN
            else:
                if field == 'open':
                    return minute_df.price.iloc[0]
                elif field == 'close':
                    return minute_df.price.iloc[-1]
                elif field == 'high':
                    return minute_df.price.max()
                elif field == 'low':
                    return minute_df.price.min()
                elif field == 'volume':
                    return minute_df.vol.sum()

    def get_realtime_bars(self, assets, frequency):
        if frequency == '1m':
            resample_freq = 'Min'
        elif frequency == '1d':
            resample_freq = 'd'
        else:
            raise ValueError("Invalid frequency specified: %s" % frequency)

        df = pd.DataFrame()

        for asset in assets:
            symbol = str(asset.symbol)
            self.subscribe_to_market_data(asset)
            self._update_bars()

            trade_prices = self._bars[symbol]['price']
            trade_sizes = self._bars[symbol]['vol']
            ohlcv = trade_prices.resample(resample_freq,
                                          label='left',
                                          closed='left').ohlc()
            ohlcv['volume'] = trade_sizes.resample(resample_freq,
                                                   label='left',
                                                   closed='left').sum()

            ohlcv.columns = pd.MultiIndex.from_product([[asset, ],
                                                        ohlcv.columns])
            df = pd.concat([df, ohlcv], axis=1)

        return df
コード例 #18
0
ファイル: tdx_bundle.py プロジェクト: huangzhengyong/zipline
def tdx_bundle(assets,
               ingest_minute,  # whether to ingest minute data, default False
               fundamental,  # whether to ingest fundamental data, default False
               environ,
               asset_db_writer,
               minute_bar_writer,
               daily_bar_writer,
               adjustment_writer,
               fundamental_writer,
               calendar,
               start_session,
               end_session,
               cache,
               show_progress,
               output_dir):
    # eg = Engine(auto_retry=True, multithread=True, best_ip=True, thread_num=1)
    eg = Engine(auto_retry=True, multithread=True, best_ip=True, thread_num=1)
    eg.connect()

    symbols = fetch_symbols(eg, assets)
    metas = []

    today = pd.to_datetime('today', utc=True)
    distance = calendar.session_distance(start_session, today)

    dates_path = join(output_dir, DATE_DIR)
    if os.path.isfile(dates_path):
        with open(dates_path, 'r') as f:
            dates_json = json.load(f)
    else:
        dates_json = {
            '1d': {},
            '1m': {}
        }

    session_bars = create_engine('sqlite:///' + join(output_dir, SESSION_BAR_DB))

    def gen_symbols_data(symbol_map, freq='1d'):
        if not session_bars.has_table(SESSION_BAR_TABLE):
            Base.metadata.create_all(session_bars.connect(), checkfirst=True,
                                     tables=[Base.metadata.tables[SESSION_BAR_TABLE]])

        func = partial(fetch_single_equity, eg)
        now = pd.to_datetime('now', utc=True)
        if end_session >= now.normalize():
            end = now.normalize()
            if now.tz_convert('Asia/Shanghai').time() < datetime.time(15, 5):
                end = end - pd.Timedelta('1 D')
        else:
            end = end_session
        end_idx = calendar.all_sessions.searchsorted(end)
        if calendar.all_sessions[end_idx] > end:
            end = calendar.all_sessions[end_idx -1]

        for index, symbol in symbol_map.iteritems():
            try:
                start = pd.to_datetime(dates_json[freq][symbol], utc=True) + pd.Timedelta('1 D')
                start = calendar.all_sessions[calendar.all_sessions.searchsorted(start)]
                if start > end:
                    if freq == '1d'and symbol in dates_json[freq]:
                        data = pd.read_sql(
                            "select * from {} where id = {} order by day ASC ".format(SESSION_BAR_TABLE, int(symbol)),
                            session_bars, index_col='day')
                        data.index = pd.to_datetime(data.index)
                        yield int(symbol), data
                    else:
                        yield int(symbol), pd.DataFrame()
                    continue
            except KeyError:
                start = start_session
            if freq == '1m':
                single_distance = calendar.session_distance(start, end)
                if single_distance >= 100:
                    func = eg.get_k_data
            data = reindex_to_calendar(
                calendar,
                func(symbol, start, end, freq),
                start_session=start, end_session=end,
                freq=freq,
            )
            if data is None or data.empty:
                if freq == '1d'and symbol in dates_json[freq]:
                    data = pd.read_sql(
                        "select * from {} where id = {} order by day ASC ".format(SESSION_BAR_TABLE, int(symbol)),
                        session_bars, index_col='day')
                    data.index = pd.to_datetime(data.index)
                    yield int(symbol), data
                continue
            if freq == '1d':
                if data.close.isnull()[0]:  # padding fill error if the first is NaN
                    data2 = pd.read_sql(
                        "select * from {} where id = {} order by day desc limit 1 ".format(SESSION_BAR_TABLE, int(symbol)),
                        session_bars, index_col='day')
                    if data2.empty:
                        data = data[data.close.notnull()]
                    else:
                        data["close"][0] = data2["close"][0]
                        fillna(data)
                data.to_sql(SESSION_BAR_TABLE, session_bars.connect(), if_exists='append', index_label='day')
                if symbol in dates_json[freq]:
                    data = pd.read_sql(
                        "select * from {} where id = {} order by day ASC ".format(SESSION_BAR_TABLE, int(symbol)),
                        session_bars, index_col='day')
                    data.index = pd.to_datetime(data.index)
            dates_json[freq][symbol] = data.index[-1].strftime('%Y%m%d')
            yield int(symbol), data

            with open(dates_path, 'w') as f:
                json.dump(dates_json, f)

    symbol_map = symbols.symbol

    assets = set([int(s) for s in symbol_map])
    daily_bar_writer.write(gen_symbols_data(symbol_map, freq="1d"), assets=assets, show_progress=show_progress)

    splits, dividends, shares = fetch_splits_and_dividends(eg, symbols, start_session, end_session)
    metas = pd.read_sql("select id as symbol,min(day) as start_date,max(day) as end_date from bars group by id;",
                        session_bars,
                        parse_dates=['start_date','end_date']
                        )
    metas['symbol'] = metas['symbol'].apply(lambda x:format(x,'06'))
    metas['first_traded'] = metas['start_date']
    metas['auto_close_date'] = metas['end_date']

    symbols = symbols.set_index('symbol', drop=False).join(metas.set_index('symbol'), how='inner')
    asset_db_writer.write(symbols)
    adjustment_writer.write(
        splits=splits,
        dividends=dividends,
        shares=shares
    )

    if fundamental:
        logger.info("writing fundamental data:")
        try:
            fundamental_writer.write(start_session, end_session)
        except Exception as e:
            pass

    if ingest_minute:
        with click.progressbar(gen_symbols_data(symbol_map, freq="1m"),
                               label="Merging minute equity files:",
                               length=len(assets),
                               item_show_func=lambda e: e if e is None else str(e[0]),
                               ) as bar:
            minute_bar_writer.write(bar, show_progress=False)

    eg.exit()
コード例 #19
0
ファイル: tdx_shipane_broker.py プロジェクト: lhztop/zipline
class TdxShipaneBroker(TdxBroker):

    def __init__(self, tdx_uri, shipane_client, account_id=None):
        self._shipane_client = shipane_client
        self._orders = {}
        self.currency = 'RMB'
        self._subscribed_assets = []
        self._bars = {}
        self._bars_update_dt = None
        self._bars_update_interval = pd.tslib.Timedelta('5 S')
        self._mkt_client = Engine(auto_retry=True, best_ip=True)
        self._mkt_client.connect()
        # super(TdxShipaneBroker, self).__init__(tdx_uri, account_id)

    @property
    def positions(self):
        now = datetime.datetime.now()
        z_positions = protocol.Positions()
        for pos in self._shipane_client.positions():
            if isinstance(pos, list):
                pos = TdxPosition(*pos)
            sid = pos.sid

            z_position = protocol.Position(symbol(sid))
            z_position.available = pos.available
            z_position.amount = pos.amount
            z_position.cost_basis = pos.cost_basis
            z_position.last_sale_price = pos.last_sale_price
            z_position.last_sale_date = now
            z_positions[symbol(sid)] = z_position

        return z_positions

    @property
    def portfolio(self):
        z_portfolio = protocol.Portfolio()
        pfo = self._shipane_client.portfolio()
        if isinstance(pfo, list):
            pfo = TdxPortfolio(*pfo)
        z_portfolio.capital_used = None  # TODO
        z_portfolio.starting_cash = None
        z_portfolio.portfolio_value = pfo.portfolio_value
        z_portfolio.pnl = None
        z_portfolio.returns = None
        z_portfolio.cash = pfo.cash
        z_portfolio.start_date = None
        z_portfolio.positions = self.positions
        z_portfolio.positions_value = pfo.positions_value
        z_portfolio.position_exposure = z_portfolio.positions_value / (z_portfolio.positions_value + z_portfolio.cash)

        return z_portfolio

    def order(self, asset, amount, style):
        code = asset.symbol

        if amount > 0:
            action = BUY
        else:
            action = SELL

        is_busy = (amount > 0)
        if isinstance(style, MarketOrder):
            order_type = FIVE_LEVEL_MARKET_ORDER
            price = 0.0
        elif isinstance(style, LimitOrder):
            order_type = LIMIT_CHARGE
            price = style.get_limit_price(is_busy)
        elif isinstance(style, StopOrder):
            raise Exception("stop order is not supported")
        elif isinstance(style, StopLimitOrder):
            raise Exception("stop limit order is not supported")

        data, err = self._shipane_client.order(code, abs(amount), price, action, order_type)
        if isinstance(data,list):
            if len(data) > 0:
                data = OrderRt(*data)
            else:
                return None
        order_id = str(data.order_id)
        zp_order = self._get_or_create_zp_order(order_id)

        log.info("Placing order-{order_id}: "
                 "{action} {qty} {symbol} with {order_type}, price = {price}".format(
            order_id=order_id,
            action=action,
            qty=amount,
            symbol=code,
            order_type=order_type,
            price=price
        ))

        return zp_order

    @property
    def orders(self):
        self._update_orders()
        return self._orders

    def _get_or_create_zp_order(self, order_id):
        zp_order_id = self._tdx_to_zp_order_id(order_id)
        if zp_order_id in self.orders:
            return self._orders[zp_order_id]

        if isinstance(order_id, list):  # handle rpc response for namedtuple object
            order = TdxOrder(*order_id)
        self._orders[zp_order_id] = self.tdx_order_to_zipline_order(order)
        return self._orders[zp_order_id]

    # amount 可正数可负数
    def _create_zp_order(self, order_id, asset, price, amount, order_type):
        zp_order_id = self._tdx_to_zp_order_id(order_id)
        if zp_order_id in self._orders:
            return self._orders[zp_order_id]

        dt = pd.to_datetime("now", utc=True)
        self._orders[zp_order_id] = ZPOrder(
            dt=dt,
            asset=asset,
            amount=amount,
            stop=None,
            limit=price if order_type is LIMIT_CHARGE else None,
            id=zp_order_id,
            broker_order_id=order_id
        )

        return self._orders[zp_order_id]

    def _tdx_to_zp_order_id(self, order_id):
        return "TDX-{date}-{account_id}-{order_id}".format(
            date=str(pd.to_datetime('today').date()),
            account_id="XXX",
            order_id=order_id
        )

    def tdx_order_to_zipline_order(self, order):
        if order.status is not None and 'CANCEL' == order.status:
            zp_status = ZP_ORDER_STATUS.CANCELLED
        elif order.filled == 0:
            zp_status = ZP_ORDER_STATUS.OPEN
        else:
            zp_status = ZP_ORDER_STATUS.FILLED

        zp_order_id = self._tdx_to_zp_order_id(order.order_id)

        od = ZPOrder(
            dt=pd.to_datetime(order.dt),
            asset=symbol(order.symbol),
            amount=order.amount,
            filled=order.filled,
            stop=None,
            limit=order.price,  # TODO 市价单和限价单
            id=zp_order_id,
        )
        od.broker_order_id = order.order_id
        od.status = zp_status

        return od

    def _update_orders(self):
        ods = self._shipane_client.orders()
        if ods is None or len(ods) <= 0:
            return
        for tdx_order_id, tdx_order in iteritems(ods):
            if isinstance(tdx_order, list):  # handle rpc response for namedtuple object
                tdx_order = TdxOrder(*tdx_order)
            zp_order_id = self._tdx_to_zp_order_id(tdx_order_id)
            self._orders[zp_order_id] = self.tdx_order_to_zipline_order(tdx_order)


    @property
    def transactions(self):
        # TODO: do we need the tx record now?
        # t = self._client.transactions()
        rt = {}
        return rt

    def cancel_order(self, order_id):
        if order_id not in self.orders:  # order become transaction, can't cancel
            return
        tdx_order_id = self.orders[order_id].broker_order_id
        self._shipane_client.cancel_orders(0, tdx_order_id)
コード例 #20
0
def main():
    engine = Engine(best_ip=True, thread_num=1)
    with engine.connect():
        engine.get_k_data('000001', '20161201', '20171231', '1m')
コード例 #21
0
ファイル: tdx_bundle.py プロジェクト: xujun05/nzl
def tdx_bundle(
        assets,
        ingest_minute,  # whether to ingest minute data, default False
        fundamental,  # whether to ingest fundamental data, default False
        environ,
        asset_db_writer,
        minute_bar_writer,
        daily_bar_writer,
        adjustment_writer,
        fundamental_writer,
        calendar,
        start_session,
        end_session,
        cache,
        show_progress,
        output_dir):
    eg = Engine(auto_retry=True, multithread=True, best_ip=True, thread_num=8)
    eg.connect()

    symbols = fetch_symbols(eg, assets)
    metas = []

    today = pd.to_datetime('today', utc=True)
    distance = calendar.session_distance(start_session, today)

    dates_path = join(output_dir, DATE_DIR)
    if os.path.isfile(dates_path):
        with open(dates_path, 'r') as f:
            dates_json = json.load(f)
    else:
        dates_json = {'1d': {}, '1m': {}}

    session_bars = create_engine('sqlite:///' +
                                 join(output_dir, SESSION_BAR_DB))

    def gen_symbols_data(symbol_map, freq='1d'):
        if not session_bars.has_table(SESSION_BAR_TABLE):
            Base.metadata.create_all(
                session_bars.connect(),
                checkfirst=True,
                tables=[Base.metadata.tables[SESSION_BAR_TABLE]])

        func = partial(fetch_single_equity, eg)
        now = pd.to_datetime('now', utc=True)
        if end_session >= now.normalize():
            end = now.normalize()
            if now.tz_convert('Asia/Shanghai').time() < datetime.time(15, 5):
                end = end - pd.Timedelta('1 D')
        else:
            end = end_session

        if freq == '1m':
            if distance >= 100:
                func = eg.get_k_data

        for index, symbol in symbol_map.iteritems():
            try:
                start = pd.to_datetime(dates_json[freq][symbol],
                                       utc=True) + pd.Timedelta('1 D')
                if start >= end:
                    continue
            except KeyError:
                start = start_session
            data = reindex_to_calendar(
                calendar,
                func(symbol, start, end, freq),
                freq=freq,
            )
            if freq == '1d':
                data.to_sql(SESSION_BAR_TABLE,
                            session_bars.connect(),
                            if_exists='append',
                            index_label='day')
                if symbol in dates_json[freq]:
                    data = pd.read_sql(
                        "select * from {} where id = {} order by day ASC ".
                        format(SESSION_BAR_TABLE, int(symbol)),
                        session_bars,
                        index_col='day')
                    data.index = pd.to_datetime(data.index)
            dates_json[freq][symbol] = end.strftime('%Y%m%d')
            yield int(symbol), data

            with open(dates_path, 'w') as f:
                json.dump(dates_json, f)

    symbol_map = symbols.symbol

    assets = set([int(s) for s in symbol_map])
    daily_bar_writer.write(gen_symbols_data(symbol_map, freq="1d"),
                           assets=assets,
                           show_progress=show_progress)

    if ingest_minute:
        with click.progressbar(
                gen_symbols_data(symbol_map, freq="1m"),
                label="Merging minute equity files:",
                length=len(assets),
                item_show_func=lambda e: e if e is None else str(e[0]),
        ) as bar:
            minute_bar_writer.write(bar, show_progress=False)

    splits, dividends, shares = fetch_splits_and_dividends(
        eg, symbols, start_session, end_session)
    metas = pd.read_sql(
        "select id as symbol,min(day) as start_date,max(day) as end_date from bars group by id;",
        session_bars,
        parse_dates=['start_date', 'end_date'])
    metas['symbol'] = metas['symbol'].apply(lambda x: format(x, '06'))
    metas['first_traded'] = metas['start_date']
    metas['auto_close_date'] = metas['end_date']

    symbols = symbols.set_index('symbol',
                                drop=False).join(metas.set_index('symbol'),
                                                 how='inner')
    asset_db_writer.write(symbols)
    adjustment_writer.write(splits=splits, dividends=dividends, shares=shares)

    if fundamental:
        logger.info("writing fundamental data:")
        try:
            fundamental_writer.write(start_session, end_session)
        except Exception as e:
            pass

    eg.exit()
コード例 #22
0
ファイル: tdx_bundle.py プロジェクト: ekin1106/zipline
def tdx_bundle(assets,
               ingest_minute,  # whether to ingest minute data, default False
               overwrite,
               environ,
               asset_db_writer,
               minute_bar_writer,
               daily_bar_writer,
               adjustment_writer,
               calendar,
               start_session,
               end_session,
               cache,
               show_progress,
               output_dir):
    eg = Engine(auto_retry=True, multithread=True, best_ip=True, thread_num=8)
    eg.connect()

    symbols = fetch_symbols(eg, assets)
    metas = []

    today = pd.to_datetime('today',utc=True)
    distance = calendar.session_distance(start_session, today)
    if ingest_minute and not overwrite and (start_session < today - pd.DateOffset(years=3)):
        minute_start = calendar.all_sessions[searchsorted(calendar.all_sessions, today - pd.DateOffset(years=3))]
        logger.warning(
            "overwrite start_session for minute bars to {}(3 years),"
            " to fetch minute data before that, please add '--overwrite True'".format(minute_start))
    else:
        minute_start = start_session

    def gen_symbols_data(symbol_map, freq='1d'):
        func = partial(fetch_single_equity, eg)
        start = start_session
        end = end_session

        if freq == '1m':
            if distance >= 100:
                func = eg.get_k_data
                start = minute_start

        for index, symbol in symbol_map.iteritems():
            data = reindex_to_calendar(
                calendar,
                func(symbol, start, end, freq),
                freq=freq,
            )
            if freq == '1d':
                metas.append(get_meta_from_bars(data))
            yield int(symbol), data

    symbol_map = symbols.symbol

    assets = set([int(s) for s in symbol_map])
    daily_bar_writer.write(gen_symbols_data(symbol_map, freq="1d"), assets=assets, show_progress=show_progress)

    if ingest_minute:
        with click.progressbar(gen_symbols_data(symbol_map, freq="1m"),
                               label="Merging minute equity files:",
                               length=len(assets),
                               item_show_func=lambda e: e if e is None else str(e[0]),
                               ) as bar:
            minute_bar_writer.write(bar, show_progress=False)

    symbols = pd.concat([symbols, pd.DataFrame(data=metas)], axis=1)
    splits, dividends = fetch_splits_and_dividends(eg, symbols)
    symbols.set_index('symbol', drop=False, inplace=True)
    asset_db_writer.write(symbols)
    adjustment_writer.write(
        splits=splits,
        dividends=dividends
    )

    eg.exit()
コード例 #23
0
def ensure_benchmark_data(symbol, first_date, last_date, now, trading_day):
    """
    Ensure we have benchmark data for `symbol` from `first_date` to `last_date`

    Parameters
    ----------
    symbol : str
        The symbol for the benchmark to load.
    first_date : pd.Timestamp
        First required date for the cache.
    last_date : pd.Timestamp
        Last required date for the cache.
    now : pd.Timestamp
        The current time.  This is used to prevent repeated attempts to
        re-download data that isn't available due to scheduling quirks or other
        failures.
    trading_day : pd.CustomBusinessDay
        A trading day delta.  Used to find the day before first_date so we can
        get the close of the day prior to first_date.

    We attempt to download data unless we already have data stored at the data
    cache for `symbol` whose first entry is before or on `first_date` and whose
    last entry is on or after `last_date`.

    If we perform a download and the cache criteria are not satisfied, we wait
    at least one hour before attempting a redownload.  This is determined by
    comparing the current time to the result of os.path.getmtime on the cache
    path.
    """
    path = get_data_filepath(get_benchmark_filename(symbol))

    # If the path does not exist, it means the first download has not happened
    # yet, so don't try to read from 'path'.
    if os.path.exists(path):
        try:
            data = pd.Series.from_csv(path).tz_localize('UTC')
            if has_data_for_dates(data, first_date, last_date):
                return data

            # Don't re-download if we've successfully downloaded and written a
            # file in the last hour.
            last_download_time = last_modified_time(path)
            if (now - last_download_time) <= ONE_HOUR:
                logger.warn(
                    "Refusing to download new benchmark data because a "
                    "download succeeded at %s." % last_download_time)
                return data

        except (OSError, IOError, ValueError) as e:
            # These can all be raised by various versions of pandas on various
            # classes of malformed input.  Treat them all as cache misses.
            logger.info(
                "Loading data for {path} failed with error [{error}].".format(
                    path=path,
                    error=e,
                ))
    logger.info(
        "Cache at {path} does not have data from {start} to {end}.\n"
        "Downloading benchmark data for '{symbol}'.",
        start=first_date,
        end=last_date,
        symbol=symbol,
        path=path,
    )

    engine = Engine(auto_retry=True, multithread=True, thread_num=8)
    engine.connect()
    data = engine.get_security_bars(symbol, '1d', index=True)
    data = data['close'].sort_index().tz_localize('UTC').pct_change(1).iloc[1:]
    data.index = data.index.shift(-15,
                                  '1H')  # change datetime at 15:00 to midnight
    data.to_csv(path)
    return data
コード例 #24
0
class TdxShipaneBroker(TdxBroker):

    def __init__(self, tdx_uri, shipane_client, account_id=None):
        self._shipane_client = shipane_client
        self._orders = {}
        self.currency = 'RMB'
        self._subscribed_assets = []
        self._bars = {}
        self._bars_update_dt = None
        self._bars_update_interval = pd.tslib.Timedelta('5 S')
        self._mkt_client = Engine(auto_retry=True, best_ip=True)
        self._mkt_client.connect()
        # super(TdxShipaneBroker, self).__init__(tdx_uri, account_id)

    @property
    def positions(self):
        now = datetime.datetime.now()
        z_positions = protocol.Positions()
        for pos in self._shipane_client.positions():
            if isinstance(pos, list):
                pos = TdxPosition(*pos)
            sid = pos.sid

            z_position = protocol.Position(symbol(sid))
            z_position.available = pos.available
            z_position.amount = pos.amount
            z_position.cost_basis = pos.cost_basis
            z_position.last_sale_price = pos.last_sale_price
            z_position.last_sale_date = now
            z_positions[symbol(sid)] = z_position

        return z_positions

    @property
    def portfolio(self):
        z_portfolio = protocol.Portfolio()
        pfo = self._shipane_client.portfolio()
        if isinstance(pfo, list):
            pfo = TdxPortfolio(*pfo)
        z_portfolio.capital_used = None  # TODO
        z_portfolio.starting_cash = None
        z_portfolio.portfolio_value = pfo.portfolio_value
        z_portfolio.pnl = None
        z_portfolio.returns = None
        z_portfolio.cash = pfo.cash
        z_portfolio.start_date = None
        z_portfolio.positions = self.positions
        z_portfolio.positions_value = pfo.positions_value
        z_portfolio.position_exposure = z_portfolio.positions_value / (z_portfolio.positions_value + z_portfolio.cash)

        return z_portfolio

    def order(self, asset, amount, style):
        code = asset.symbol

        if amount > 0:
            action = BUY
        else:
            action = SELL

        is_busy = (amount > 0)
        if isinstance(style, MarketOrder):
            order_type = FIVE_LEVEL_MARKET_ORDER
            price = 0.0
        elif isinstance(style, LimitOrder):
            order_type = LIMIT_CHARGE
            price = style.get_limit_price(is_busy)
        elif isinstance(style, StopOrder):
            raise Exception("stop order is not supported")
        elif isinstance(style, StopLimitOrder):
            raise Exception("stop limit order is not supported")

        data, err = self._shipane_client.order(code, abs(amount), price, action, order_type)
        if isinstance(data,list):
            if len(data) > 0:
                data = OrderRt(*data)
            else:
                return None
        order_id = str(data.order_id)
        zp_order = self._get_or_create_zp_order(order_id)

        log.info("Placing order-{order_id}: "
                 "{action} {qty} {symbol} with {order_type}, price = {price}".format(
            order_id=order_id,
            action=action,
            qty=amount,
            symbol=code,
            order_type=order_type,
            price=price
        ))

        return zp_order

    @property
    def orders(self):
        self._update_orders()
        return self._orders

    def _get_or_create_zp_order(self, order_id):
        zp_order_id = self._tdx_to_zp_order_id(order_id)
        if zp_order_id in self.orders:
            return self._orders[zp_order_id]

        if isinstance(order, list):  # handle rpc response for namedtuple object
            order = TdxOrder(*order)
        self._orders[zp_order_id] = self.tdx_order_to_zipline_order(order)
        return self._orders[zp_order_id]

    # amount 可正数可负数
    def _create_zp_order(self, order_id, asset, price, amount, order_type):
        zp_order_id = self._tdx_to_zp_order_id(order_id)
        if zp_order_id in self._orders:
            return self._orders[zp_order_id]

        dt = pd.to_datetime("now", utc=True)
        self._orders[zp_order_id] = ZPOrder(
            dt=dt,
            asset=asset,
            amount=amount,
            stop=None,
            limit=price if order_type is LIMIT_CHARGE else None,
            id=zp_order_id,
            broker_order_id=order_id
        )

        return self._orders[zp_order_id]

    def _tdx_to_zp_order_id(self, order_id):
        return "TDX-{date}-{account_id}-{order_id}".format(
            date=str(pd.to_datetime('today').date()),
            account_id="XXX",
            order_id=order_id
        )

    def tdx_order_to_zipline_order(self, order):
        if order.status is not None and 'CANCEL' == order.status:
            zp_status = ZP_ORDER_STATUS.CANCELLED
        elif order.filled == 0:
            zp_status = ZP_ORDER_STATUS.OPEN
        else:
            zp_status = ZP_ORDER_STATUS.FILLED

        zp_order_id = self._tdx_to_zp_order_id(order.order_id)

        od = ZPOrder(
            dt=pd.to_datetime(order.dt),
            asset=symbol(order.symbol),
            amount=order.amount,
            filled=order.filled,
            stop=None,
            limit=order.price,  # TODO 市价单和限价单
            id=zp_order_id,
        )
        od.broker_order_id = order.order_id
        od.status = zp_status

        return od

    def _update_orders(self):
        ods = self._shipane_client.orders()
        if ods is None or len(ods) <= 0:
            return
        for tdx_order_id, tdx_order in iteritems(ods):
            if isinstance(tdx_order, list):  # handle rpc response for namedtuple object
                tdx_order = TdxOrder(*tdx_order)
            zp_order_id = self._tdx_to_zp_order_id(tdx_order_id)
            self._orders[zp_order_id] = self.tdx_order_to_zipline_order(tdx_order)


    @property
    def transactions(self):
        # TODO: do we need the tx record now?
        # t = self._client.transactions()
        rt = {}
        return rt

    def cancel_order(self, order_id):
        if order_id not in self.orders:  # order become transaction, can't cancel
            return
        tdx_order_id = self.orders[order_id].broker_order_id
        self._shipane_client.cancel_orders(0, tdx_order_id)