Esempio n. 1
0
    def __init__(self, pf_name):

        super().__init__()
        self.pf_name = pf_name
        self.positions = defaultdict(Asset)

        self._logger_ = logs.get_logger(SubPortfolio, types='stream')
Esempio n. 2
0
def latest_file(path_name, keyword='', ext='', **kwargs) -> str:
    """
    Latest modified file in folder

    Args:
        path_name: full path name
        keyword: keyword to search
        ext: file extension

    Returns:
        str: latest file name

    Examples:
        >>> target_folder = Path(abspath(__file__)) / 'tests/folders'
        >>> _ = target_folder.joinpath('test_2.yml').write_text('modified: 1')
        >>> latest_file(target_folder, keyword='test', ext='yml').split('/')[-1]
        'test_2.yml'
        >>> latest_file(target_folder / 'notfound')
        ''
    """
    files = sort_by_modified(
        all_files(path_name=path_name,
                  keyword=keyword,
                  ext=ext,
                  full_path=True))

    if not files:
        from xone import logs

        logger = logs.get_logger(latest_file,
                                 level=kwargs.pop('log', 'warning'))
        logger.debug(f'file is not found in folder: {path_name}')
        return ''

    return str(files[0]).replace('\\', '/')
Esempio n. 3
0
    def __init__(self, init_cash, trade_on='price', mark_on='price', **kwargs):
        """
        Args:
            init_cash: initial cash
            trade_on: field to trade on
            mark_on: price field for mark-to-market purpose
            **kwargs: other kwargs for the class
        """
        super().__init__()
        self.init_cash = init_cash
        self.trade_on = trade_on
        self.mark_on = mark_on

        if trade_on in ['bid_ask', 'ask_bid']:
            self._buy_on_, self._sell_on_ = 'ask', 'bid'
        else:
            self._buy_on_, self._sell_on_ = trade_on, trade_on

        # Internal values to track positions and performance
        self._cash_ = init_cash
        self._commission_ = defaultdict(float)
        self._market_value_ = 0.
        self._margin_ = 0.
        self._positions_ = defaultdict(Asset)
        self._sub_pf_ = defaultdict(SubPortfolio)
        self._performance_ = []
        self._tolerance_ = kwargs.pop('tolerance', 5e5)
        self._cur_dt_ = None
        self.info = kwargs

        self._logger_ = logs.get_logger(Portfolio,
                                        types='stream',
                                        level='info')
Esempio n. 4
0
    def __init__(self, port_name, asset: Asset, snapshot, quantity, trade_on):
        """
        Args:
            port_name: portfolio name
            asset: asset
            snapshot: market snapshot
            quantity: quantity, can be + / -
            trade_on: price field to trade
        """
        super().__init__()

        self.port_name = port_name
        self.ticker = asset.ticker
        self.price = snapshot[self.ticker][trade_on]
        self.lot_size = asset.lot_size
        self.quantity = quantity

        self._comms_ = asset.comms.calculate(transaction=Trans(
            quantity=quantity * self.lot_size, fill_cost=self.price
        ))
        self._logger_ = logs.get_logger(Transaction, types='stream')

        self.total_notional = round(self.price * self.lot_size * quantity, 2)
        self.comm_total = self._comms_.total_comm
        self.comm_in_bps = self._comms_.in_bps

        self._logger_.info(
            f'{port_name}:{self.ticker}:qty={show_qty(quantity)}:'
            f'cost={show_value(self.price, digit=2)}:lot={show_qty(self.lot_size)}:'
            f'notional={show_value(self.total_notional)}:'
            f'comms={self.comm_total}:in_bps={self.comm_in_bps}'
        )
Esempio n. 5
0
    def __init__(self,
                 timestamp,
                 strategy: str,
                 assets: list,
                 order_type='MKT',
                 target_value=None,
                 weights=None,
                 target_qty=None,
                 **kwargs):
        """
        Args:
            assets: list of assets
            order_type: order type, 'MKT' (default) or 'LMT'
            target_value: target notional
            weights: dict, weights of each asset
            target_qty: dict, target quantity for each asset
        """
        self._logger_ = logs.get_logger(SignalEvent, types='steram')
        assert (target_value is None) and (target_qty is None), ValueError(
            f'[{self.__class__.__name__}] Both target value and quantity are empty'
        )
        assert all(isinstance(asset, Asset) for asset in assets), ValueError(
            f'[{self.__class__.__name__}] Not all assets are of Asset class')

        super().__init__()
        self.timestamp = pd.Timestamp(timestamp)
        self.strategy = strategy
        self.assets = assets
        self.order_type = order_type
        self.target_value = target_value
        self.weights = proper_weights(assets=assets, weights=weights)
        self.target_qty = target_qty
        self.info = kwargs
        self._order_type_ = LimitOrderEvent \
            if order_type.upper() == 'LMT' else MarketOrderEvent
Esempio n. 6
0
def page_source(url: str,
                browser: str = '',
                click: str = '',
                headless=True,
                *args) -> PageSource:
    """
    Page source from url

    Args:
        url: url
        browser: one of firefox, chrome and ie
        click: element to click - useful for scroll down page
               will use browser if given - default browser Chrome
        headless: whether to show browser

    Returns:
        PageSource
    """
    logger = logs.get_logger(page_source)

    if click and (not browser): browser = 'chrome'
    if not browser:
        page = requests.get(url)
        if page.status_code == 200:
            return PageSource(
                source=page.content,
                soup=BeautifulSoup(page.content, 'lxml'),
            )
        else:
            logger.warning(
                f'Invalid status code {page.status_code} for url:\n{url}')
            return PageSource(source='', soup=BeautifulSoup('', 'lxml'))

    if browser not in BROWSERS:
        raise LookupError(f'Cannot find browser: {browser}.\n'
                          f'Valid browsers: {list(BROWSERS.keys())}.')

    with get_browser(browser, headless=headless, *args) as driver:
        driver.get(url=url)
        if click:
            try:
                driver.find_element_by_xpath(click).click()
            except (NoSuchElementException,
                    ElementClickInterceptedException) as e:
                logger.error(e)
            time.sleep(1)
        return PageSource(
            source=driver.page_source,
            soup=BeautifulSoup(driver.page_source, 'lxml'),
        )
Esempio n. 7
0
def load_file(data_file: str, load_func=None, **kwargs):
    """
    Load data from cache
    """
    logger = logs.get_logger(load_file, level=kwargs.get('log', 'info'))
    if (not data_file) or (not files.exists(data_file)): return

    if callable(load_func): return load_func(data_file)

    ext = data_file.split('.')[-1]
    if ext not in LOAD_FUNC: return

    logger.debug(f'Reading from {data_file} ...')
    return LOAD_FUNC[ext](data_file)
Esempio n. 8
0
def run(func, keys, max_procs=None, affinity=None, proc_desc='', **kwargs):
    """
    Provide interface for multiprocessing

    Args:
        func: callable functions
        keys: keys in kwargs that want to use process
        max_procs: max number of processes
        affinity: CPU affinity
        proc_desc: prefix for progressbar
        **kwargs: kwargs for func
    """
    logger = logs.get_logger(run, level=kwargs.get('log', 'info'))

    if max_procs is None: max_procs = cpu_count()
    kw_arr = saturate_kwargs(keys=keys, **kwargs)
    if len(kw_arr) == 0: return

    if isinstance(affinity, int):
        try:
            import win32process
            import win32api

            win32process.SetProcessAffinityMask(win32api.GetCurrentProcess(),
                                                affinity)

        except Exception as e:
            logger.error(str(e))

    task_queue = queue.Queue()
    with tqdm(total=len(kw_arr), desc=proc_desc) as bar:
        while len(kw_arr) > 0:
            for _ in range(max_procs):
                if len(kw_arr) == 0: break
                kw = kw_arr.pop(0)
                bar.update()
                p = Process(target=func, kwargs=kw)
                p.start()
                sys.stdout.flush()
                task_queue.put(p)
            while not task_queue.empty():
                p = task_queue.get()
                p.join()
Esempio n. 9
0
    def wrapper(*args, **kwargs):

        default.update(kwargs)
        kwargs.update(default)
        cur_mod = sys.modules[func.__module__]
        logger = logs.get_logger(
            name_or_func=f'{cur_mod.__name__}.{func.__name__}', types='stream')

        root_path = cur_mod.DATA_PATH
        date_type = kwargs.pop('date_type', 'date')
        save_static = kwargs.pop('save_static', True)
        save_dynamic = kwargs.pop('save_dynamic', True)
        symbol = kwargs.get('symbol')
        file_kw = dict(func=func,
                       symbol=symbol,
                       root=root_path,
                       date_type=date_type)
        d_file = cache_file(has_date=True, **file_kw)
        s_file = cache_file(has_date=False, **file_kw)

        cached = kwargs.pop('cached', False)
        if cached and save_static and files.exists(s_file):
            logger.info(f'Reading data from {s_file} ...')
            return pd.read_parquet(s_file)

        data = func(*args, **kwargs)

        if save_static:
            files.create_folder(s_file, is_file=True)
            save_data(data=data, file_fmt=s_file, append=False)
            logger.info(f'Saved data file to {s_file} ...')

        if save_dynamic:
            drop_dups = kwargs.pop('drop_dups', None)
            files.create_folder(d_file, is_file=True)
            save_data(data=data,
                      file_fmt=d_file,
                      append=True,
                      drop_dups=drop_dups)
            logger.info(f'Saved data file to {d_file} ...')

        return data
Esempio n. 10
0
def save_file(data, data_file: str, save_func=None, **kwargs):
    """
    Save data
    """
    logger = logs.get_logger(save_file, level=kwargs.get('log', 'info'))
    if not data_file: return
    if isinstance(data, (pd.Series, pd.DataFrame)) and data.empty: return

    files.create_folder(data_file, is_file=True)
    if callable(save_func):
        logger.debug(f'Saving data to {data_file} ...')
        save_func(data=data, data_file=data_file)

    ext = data_file.split('.')[-1]
    save_kw = {}
    if ext in ['csv', 'xls', 'xlsx']: save_kw['index'] = False

    save_func = SAVE_FUNC.get(ext, '__nothing__')
    if not hasattr(data, save_func): return

    logger.debug(f'Saving data to {data_file} ...')
    getattr(data, save_func)(data_file, **save_kw)
Esempio n. 11
0
    def __init__(self, events_queue, inst_exec: bool, trade_on: str):
        """
        Args:
            inst_exec: if instant execution enabled
            trade_on: valid inputs - ['price', 'bid_ask', 'bid_ask_1', ...]
        """
        super().__init__()
        self.inst_exec = inst_exec

        self.trade_on = trade_on
        if ('bid' in trade_on) and ('ask' in trade_on):
            lvl = trade_on[-1]
            if lvl.isdigit():
                self._buy_on_, self._sell_on_ = f'ask_{lvl}', f'bid_{lvl}'
            else:
                self._buy_on_, self._sell_on_ = 'ask', 'bid'
        else:
            self._sell_on_, self._sell_on_ = trade_on, trade_on

        self._timestamp_ = None
        self._snap_ = MarketSnapshot()
        self.events_queue = events_queue

        self._logger_ = logs.get_logger(SimulationEngine, types='stream')
Esempio n. 12
0
def latest_file(path_name, keyword='', ext='', **kwargs) -> str:
    """
    Latest modified file in folder

    Args:
        path_name: full path name
        keyword: keyword to search
        ext: file extension

    Returns:
        str: latest file name

    Examples:
        >>> target_folder = f'{abspath(__file__)}/tests/folders'
        >>> latest_file(target_folder, keyword='test', ext='yml').split('/')[-1]
        'test_2.yml'
        >>> latest_file(f'{target_folder}/notfound')
        ''
    """
    files = all_files(path_name=path_name,
                      keyword=keyword,
                      ext=ext,
                      full_path=True)

    if not files:
        from xone import logs

        logger = logs.get_logger(latest_file,
                                 level=kwargs.pop('log', 'warning'))
        logger.debug(f'file is not found in folder: {path_name}')
        return ''

    modified_time = [os.path.getmtime(f) for f in files]
    files = [f for (dt, f) in sorted(zip(modified_time, files))]

    return files[-1]