コード例 #1
0
ファイル: validate.py プロジェクト: portfolio-123/data-miner
def ranking_system(ranking):
    if misc.is_str(ranking) or misc.is_int(ranking):
        return True
    elif not misc.is_dict(ranking):
        return False

    nodes = ranking.get('Nodes')
    if nodes is None:
        return '"Nodes" property required'

    is_list = misc.is_list(nodes)
    if not is_list and not misc.is_str(nodes):
        return '"Nodes" property must be a list or a string containing a XML structure'

    for key, value in ranking.items():
        if key == 'Nodes':
            pass
        elif key == 'Rank' and is_list:
            if not misc.is_str(value) or value not in ('Lower', 'Higher',
                                                       'Summation'):
                return '"Rank" property is invalid'
        elif key == 'Method':
            if not misc.is_str(value) or value.lower(
            ) not in cons.RANKING_METHOD:
                return '"Method" property is invalid'
        else:
            return f'Unexpected "{key}" property'

    if is_list:
        ret = screen_ranking_nodes(nodes)
        if not misc.is_bool(ret) or not ret:
            return ret

    return True
コード例 #2
0
ファイル: validate.py プロジェクト: portfolio-123/data-miner
def universe(univ):
    if misc.is_str(univ):
        return True
    elif not misc.is_dict(univ):
        return False

    rules = None
    starting_universe = None
    for key, value in univ.items():
        if key == 'Rules':
            if not misc.is_list(value):
                return '"Rules" property is invalid'
            rules = value
        elif key == 'Starting Universe':
            if not misc.is_number(value) and (not misc.is_str(value)
                                              or not value):
                return '"Starting Universe" property is invalid'
            starting_universe = value
        else:
            return f'Unexpected "{key}" property'

    if not rules:
        return '"Rules" property is missing'
    else:
        for key, value in enumerate(rules):
            if not misc.is_number(value) and (not misc.is_str(value)
                                              or not value):
                return f'"Rules" item #{key + 1} is empty'

    if starting_universe is None:
        return '"Starting Universe" property is missing'

    return True
コード例 #3
0
ファイル: validate.py プロジェクト: portfolio-123/data-miner
def screen_ranking(ranking):
    ret = ranking_system(ranking)
    if (misc.is_bool(ret) and ret) or not misc.is_dict(ranking):
        return ret

    has_formula = 'Formula' in ranking
    has_nodes = 'Nodes' in ranking
    if not has_formula and not has_nodes:
        return '"Formula"/"Nodes" property required'
    if has_formula and has_nodes:
        return '"Formula" and "Nodes" properties cannot be mixed'

    formula = ranking.get('Formula')
    if not misc.is_number(formula) and (not misc.is_str(formula)
                                        or not formula):
        return '"Formula" property is invalid'

    for key, value in ranking.items():
        if key == 'Formula':
            pass
        elif key == 'Lower is Better':
            if not misc.is_bool(value):
                return '"Lower is Better" property is invalid'
        else:
            return f'Unexpected "{key}" property'

    return True
コード例 #4
0
ファイル: validate.py プロジェクト: portfolio-123/data-miner
def screen_rules(rules):
    if not misc.is_list(rules):
        return False
    for rule in rules:
        if not misc.is_str(rule):
            return False
    return True
コード例 #5
0
ファイル: transform.py プロジェクト: portfolio-123/data-miner
def universe(*, value, settings: dict, api_client: Client):
    if misc.is_str(value):
        return value

    params = {'type': settings['Type'], 'startingUniverse': value['Starting Universe'], 'rules': value['Rules']}
    api_client.universe_update(params)
    return 'ApiUniverse'
コード例 #6
0
ファイル: validate.py プロジェクト: portfolio-123/data-miner
def data_univ_formulas(val):
    if not misc.is_list(val):
        return False
    for item in val:
        if not (misc.is_number(item) or misc.is_str(item) or
                (misc.is_dict(item) and len(item) == 1)):
            return False
    return True
コード例 #7
0
ファイル: validate.py プロジェクト: portfolio-123/data-miner
def data_p123_uids(val):
    if misc.is_int(val):
        val = [val]
    elif misc.is_str(val):
        val = val.split(' ')

    if not misc.is_list(val):
        return False

    for item in val:
        try:
            int(item)
        except ValueError:
            return False

    return True
コード例 #8
0
ファイル: util.py プロジェクト: portfolio-123/data-miner
def validate_data_settings(settings, logger: logging.Logger):
    if 'Start Date' not in settings:
        logger.error(
            '"Default Settings" section needs to contain the "Start Date" property'
        )
        return False

    items_def_cnt = 0
    items_def_cnt += 1 if 'P123 UIDs' in settings else 0
    items_def_cnt += 1 if 'Tickers' in settings else 0
    items_def_cnt += 1 if 'Cusips' in settings else 0
    items_def_cnt += 1 if 'Gvkeys' in settings else 0
    items_def_cnt += 1 if 'Ciks' in settings else 0
    if not items_def_cnt:
        logger.error(
            '"Default Settings" section needs to contain one of the following properties: '
            '"P123 UIDs", "Tickers", "Cusips", "Gvkeys" or "Ciks"')
        return False
    if items_def_cnt > 1:
        logger.error(
            '"Default Settings" section can only contain one of the following properties: '
            '"P123 UIDs", "Tickers", "Cusips", "Gvkeys" or "Ciks"')
        return False

    if 'P123 UIDs' in settings:
        items = settings['P123 UIDs']
    elif 'Tickers' in settings:
        items = settings['Tickers']
    elif 'Cusips' in settings:
        items = settings['Cusips']
    elif 'Gvkeys' in settings:
        items = settings['Gvkeys']
    else:
        items = settings['Ciks']
    if misc.is_int(items):
        items = [items]
    elif misc.is_str(items):
        items = items.split(' ')
    items_cnt = len(items)
    if items_cnt > 100:
        logger.error('"Default Settings" can only contain at most 100 '
                     '"P123 UIDs", "Tickers", "Cusips", "Gvkeys" or "Ciks"')
        return False
    return True
コード例 #9
0
ファイル: transform.py プロジェクト: portfolio-123/data-miner
def screen_ranking(*, value, settings: dict, api_client: Client):
    if misc.is_str(value) or misc.is_int(value):
        return value

    params = {}
    if 'Formula' in value:
        params['formula'] = value['Formula']
        if 'Lower is Better' in value:
            params['lowerIsBetter'] = value['Lower is Better']
    else:
        nodes = value['Nodes']
        if misc.is_list(nodes):
            nodes = screen_ranking_nodes_to_xml(nodes, main_rank=value.get('Rank'))

        rank_params = {'type': settings['Type'], 'nodes': nodes}
        if 'Method' in value:
            rank_params['rankingMethod'] = cons.RANKING_METHOD[value['Method'].lower()]
        api_client.rank_update(rank_params)
        params = 'ApiRankingSystem'

    return params
コード例 #10
0
ファイル: validate.py プロジェクト: portfolio-123/data-miner
def data_formula(val):
    return misc.is_int(val) or misc.is_str(val)
コード例 #11
0
ファイル: validate.py プロジェクト: portfolio-123/data-miner
def data_tickers_cusips(val):
    return misc.is_int(val) or misc.is_str(val) or misc.is_list(val)
コード例 #12
0
ファイル: validate.py プロジェクト: portfolio-123/data-miner
def from_mapping(value, **kwargs):
    return misc.is_str(value) and value.lower() in kwargs['mapping']
コード例 #13
0
ファイル: validate.py プロジェクト: portfolio-123/data-miner
def screen_ranking_nodes(nodes: list, breadcrumbs='Nodes'):
    total_weight = 0
    for idx, node in enumerate(nodes):
        if not misc.is_dict(node):
            return screen_ranking_node_error(breadcrumbs,
                                             idx,
                                             error='is invalid')

        if 'Type' not in node:
            return screen_ranking_node_error(
                breadcrumbs, idx, error='"Type" property is missing')

        node_type = node['Type']
        if not misc.is_str(node_type)\
                or node_type not in ('Composite', 'StockFormula', 'IndFormula', 'SecFormula', 'Conditional'):
            return screen_ranking_node_error(
                breadcrumbs, idx, error='"Type" property is invalid')

        weight = 0
        rank = None
        sub_nodes = None
        formula = None
        scope = None
        true_nodes = None
        false_nodes = None
        for key, value in node.items():
            if key == 'Type':
                pass
            elif key == 'Weight':
                if not misc.is_number(value) or value < 0 or value > 100:
                    return screen_ranking_node_error(
                        breadcrumbs,
                        idx,
                        node_type,
                        error='"Weight" property is invalid')
                weight = value
            elif key == 'Rank':
                if not misc.is_str(value):
                    return screen_ranking_node_error(
                        breadcrumbs,
                        idx,
                        node_type,
                        error='"Rank" property is invalid')
                rank = value
            elif key == 'Name':
                if not misc.is_number(value) and (not misc.is_str(value)
                                                  or not value):
                    return screen_ranking_node_error(
                        breadcrumbs,
                        idx,
                        node_type,
                        error='"Name" property is invalid')
            elif key == 'Nodes' and node_type == 'Composite':
                if not misc.is_list(value):
                    return screen_ranking_node_error(
                        breadcrumbs,
                        idx,
                        node_type,
                        error='"Nodes" property is invalid')
                sub_nodes = value
            elif key == 'Formula' and node_type in (
                    'Conditional', 'StockFormula', 'IndFormula', 'SecFormula'):
                if not misc.is_number(value) and (not misc.is_str(value)
                                                  or not value):
                    return screen_ranking_node_error(
                        breadcrumbs,
                        idx,
                        node_type,
                        error='"Formula" property is invalid')
                formula = value
            elif key == 'Scope' and node_type == 'StockFormula':
                if not misc.is_str(value) or not len(value):
                    return screen_ranking_node_error(
                        breadcrumbs,
                        idx,
                        node_type,
                        error='"Scope" property is invalid')
                scope = value
            elif key == 'True Nodes' and node_type == 'Conditional':
                if not misc.is_list(value):
                    return screen_ranking_node_error(
                        breadcrumbs,
                        idx,
                        node_type,
                        error='"True Nodes" property is invalid')
                true_nodes = value
            elif key == 'False Nodes' and node_type == 'Conditional':
                if not misc.is_list(value):
                    return screen_ranking_node_error(
                        breadcrumbs,
                        idx,
                        node_type,
                        error='"False Nodes" property is invalid')
                false_nodes = value
            else:
                return f'Unexpected "{key}" property'

        if idx > 0 and (weight == 0) ^ (total_weight == 0):
            return screen_ranking_node_error(
                breadcrumbs,
                idx,
                node_type,
                error='Cannot mix 0 and non 0 weight nodes')
        total_weight += weight

        if node_type == 'Composite':
            if rank and rank not in ('Higher', 'Lower', 'Summation'):
                return screen_ranking_node_error(breadcrumbs, idx, node_type,
                                                 '"Rank" property is invalid')
            if not sub_nodes:
                return screen_ranking_node_error(
                    breadcrumbs,
                    idx,
                    node_type,
                    error='"Nodes" property is missing')
            ret = screen_ranking_nodes(
                sub_nodes, f'{breadcrumbs} > {node_type} ({idx + 1})')
            if not misc.is_bool(ret) or not ret:
                return ret
        elif node_type in ('StockFormula', 'IndFormula', 'SecFormula'):
            if rank and rank not in ('Higher', 'Lower', 'Boolean'):
                return screen_ranking_node_error(breadcrumbs, idx, node_type,
                                                 '"Rank" property is invalid')
            if formula is None:
                return screen_ranking_node_error(
                    breadcrumbs, idx, node_type,
                    '"Formula" property is missing')
            if scope and scope not in ('Universe', 'Industry', 'Sector'):
                return screen_ranking_node_error(
                    breadcrumbs, idx, node_type, '"Scope" property is invalid')
        elif node_type == 'Conditional':
            if rank and rank not in ('Higher', 'Lower'):
                return screen_ranking_node_error(breadcrumbs, idx, node_type,
                                                 '"Rank" property is invalid')
            if formula is None:
                return screen_ranking_node_error(
                    breadcrumbs, idx, node_type,
                    '"Formula" property is missing')
            if not true_nodes:
                return screen_ranking_node_error(
                    breadcrumbs, idx, node_type,
                    '"True Nodes" property is missing')
            ret = screen_ranking_nodes(
                true_nodes, f'{breadcrumbs} > {node_type} ({idx + 1}) True')
            if not misc.is_bool(ret) or not ret:
                return ret
            if not false_nodes:
                return screen_ranking_node_error(
                    breadcrumbs, idx, node_type,
                    '"False Nodes" property is missing')
            ret = screen_ranking_nodes(
                false_nodes, f'{breadcrumbs} > {node_type} ({idx + 1}) False')
            if not misc.is_bool(ret) or not ret:
                return ret
    if total_weight and total_weight != 100:
        return screen_ranking_node_error(
            breadcrumbs, error='Node weights do not add up to 100')
    return True
コード例 #14
0
ファイル: transform.py プロジェクト: portfolio-123/data-miner
def data_items(*, value, **kwargs):
    if misc.is_int(value):
        value = [value]
    elif misc.is_str(value):
        value = value.split(' ')
    return value