Example #1
0
    def test_module_block(self):
        # Expression with one function def.
        dsl_source = """
def sqr(n):
    n ** 2
sqr(3)
"""
        dsl_module = dsl_parse(dsl_source)
        self.assertIsInstance(dsl_module, Module)
        self.assertEqual(str(dsl_module), dsl_source.strip())

        dsl_expr = dsl_compile(dsl_source)
        self.assertEqual(dsl_expr.evaluate(), 9)

        dsl_value = dsl_eval(dsl_source)
        self.assertEqual(dsl_value, 9)

        # Expression with two function defs.
        dsl_source = """
def add(a, b):
    a + b
def mul(a, b):
    a if b == 1 else add(a, mul(a, b - 1))
mul(3, 3)
"""
        dsl_module = dsl_parse(dsl_source)
        self.assertIsInstance(dsl_module, Module)
        self.assertEqual(str(dsl_module), dsl_source.strip())

        dsl_expr = dsl_compile(dsl_source)
        #        self.assertEqual(str(dsl_expr), "")
        self.assertEqual(dsl_expr.evaluate(), 9)

        dsl_value = dsl_eval(dsl_source)
        self.assertEqual(dsl_value, 9)
Example #2
0
    def test_module_block(self):
        # Expression with one function def.
        dsl_source = """
def sqr(n):
    n ** 2
sqr(3)
"""
        dsl_module = dsl_parse(dsl_source)
        self.assertIsInstance(dsl_module, Module)
        self.assertEqual(str(dsl_module), dsl_source.strip())

        dsl_expr = dsl_compile(dsl_source)
        self.assertEqual(dsl_expr.evaluate(), 9)

        dsl_value = dsl_eval(dsl_source)
        self.assertEqual(dsl_value, 9)

        # Expression with two function defs.
        dsl_source = """
def add(a, b):
    a + b
def mul(a, b):
    a if b == 1 else add(a, mul(a, b - 1))
mul(3, 3)
"""
        dsl_module = dsl_parse(dsl_source)
        self.assertIsInstance(dsl_module, Module)
        self.assertEqual(str(dsl_module), dsl_source.strip())

        dsl_expr = dsl_compile(dsl_source)
#        self.assertEqual(str(dsl_expr), "")
        self.assertEqual(dsl_expr.evaluate(), 9)

        dsl_value = dsl_eval(dsl_source)
        self.assertEqual(dsl_value, 9)
Example #3
0
def dsl_compile(dsl_source, filename='<unknown>', is_parallel=None, dsl_classes=None, compile_kwds=None, **extraCompileKwds):
    """
    Returns a DSL expression, created according to the given DSL source module.

    That is, if the source module contains a function def and an expression which
    calls that function, then the expression's function call will be evaluated
    and the resulting DSL expression will be substituted for the function call
    in the module's expression, so that calls to user defined functions are eliminated
    and a single DSL expression is obtained.

    If the source module contains a function def, but no expression, the module is compiled
    into a function def object. Calling .apply() on a function def object will return a DSL
    expression object, which can be evaluated by calling its .evaluate() method.
    """
    if compile_kwds is None:
        compile_kwds = DslNamespace()
    assert isinstance(compile_kwds, dict)
    compile_kwds.update(extraCompileKwds)

    # Parse the source into a DSL module object.
    dsl_module = dsl_parse(dsl_source, filename=filename, dsl_classes=dsl_classes)

    assert isinstance(dsl_module, Module)

    # Compile the module into either a dependency graph
    # if 'is_parallel' is True, otherwise a single primitive expression.
    return compile_dsl_module(dsl_module, DslNamespace(), compile_kwds, is_dependency_graph=is_parallel)
Example #4
0
def identify_simulation_requirements(dependency_graph_id,
                                     call_requirement_repo, call_link_repo,
                                     call_dependencies_repo,
                                     market_dependencies_repo,
                                     observation_date, requirements):
    assert isinstance(call_requirement_repo, CallRequirementRepository)
    assert isinstance(call_link_repo, CallLinkRepository)

    all_perturbation_dependencies = {}

    for call_id in regenerate_execution_order(dependency_graph_id,
                                              call_link_repo):

        # Get the stubbed expression.
        call_requirement = call_requirement_repo[call_id]
        assert isinstance(call_requirement, CallRequirement)

        if call_requirement._dsl_expr is not None:
            dsl_expr = call_requirement._dsl_expr
        else:
            dsl_module = dsl_parse(call_requirement.dsl_source)
            dsl_expr = dsl_module.body[0]
            call_requirement._dsl_expr = dsl_expr
        assert isinstance(dsl_expr, DslObject), dsl_expr

        # Todo: Consolidate 'date' attributes to be a single element (rather than a possibly long sum expression).

        # Identify this call's requirements for simulated prices.
        simulation_requirements = set()
        present_time = call_requirement.effective_present_time or observation_date
        dsl_expr.identify_price_simulation_requirements(
            simulation_requirements, present_time=present_time)

        # Register the simulation requirements for each call (needed during evaluation).
        register_simulated_price_requirements(call_id,
                                              list(simulation_requirements))

        # Update the simulation requirements (needed for the market simulation).
        requirements.update(simulation_requirements)

        # Identify this call's perturbation dependencies.
        perturbation_dependencies = set()
        dsl_expr.identify_perturbation_dependencies(perturbation_dependencies,
                                                    present_time=present_time)

        # Add the expression's perturbation dependencies to the perturbation dependencies of its call dependencies.
        call_dependencies = call_dependencies_repo[call_id]
        assert isinstance(call_dependencies,
                          CallDependencies), call_dependencies
        for dependency_id in call_dependencies.dependencies:
            dependency_perturbation_dependencies = all_perturbation_dependencies[
                dependency_id]
            perturbation_dependencies.update(
                dependency_perturbation_dependencies)
        # Register the perturbation dependencies in the repo (needed when evaluating the call).
        register_perturbation_dependencies(call_id,
                                           list(perturbation_dependencies))

        # Save the pertubation dependencies for this call, so they are available for the dependent calls.
        all_perturbation_dependencies[call_id] = perturbation_dependencies
Example #5
0
def dsl_compile(dsl_source,
                filename='<unknown>',
                dsl_classes=None,
                compile_kwds=None,
                **extraCompileKwds):
    """
    Returns a DSL expression, created according to the given DSL source module.

    That is, if the source module contains a function def and an expression which
    calls that function, then the expression's function call will be evaluated
    and the resulting DSL expression will be substituted for the function call
    in the module's expression, so that calls to user defined functions are eliminated
    and a single DSL expression is obtained.

    If the source module contains a function def, but no expression, the module is compiled
    into a function def object. Calling .apply() on a function def object will return a DSL
    expression object, which can be evaluated by calling its .evaluate() method.
    """
    if compile_kwds is None:
        compile_kwds = DslNamespace()
    # assert isinstance(compile_kwds, dict)
    compile_kwds.update(extraCompileKwds)

    # Parse the source into a DSL module object.
    dsl_module = dsl_parse(dsl_source,
                           filename=filename,
                           dsl_classes=dsl_classes)

    # assert isinstance(dsl_module, Module)

    # Compile the module into either a dependency graph
    # if 'is_parallel' is True, otherwise a single primitive expression.
    return compile_dsl_module(dsl_module, DslNamespace(), compile_kwds)
Example #6
0
    def get_evaluation_kwds(self, dsl_source, effective_present_time):
        evaluation_kwds = self.run_kwds.copy()

        from quantdsl.services import list_fixing_dates
        from quantdsl.domain.services.parser import dsl_parse
        stubbed_module = dsl_parse(dsl_source)
        assert isinstance(stubbed_module, Module)
        # market_names = find_market_names(stubbed_module)
        fixing_dates = list_fixing_dates(stubbed_module)
        if effective_present_time is not None:
            fixing_dates.append(effective_present_time)

        # return evaluation_kwds
        # Rebuild the data structure (there was a problem, but I can't remember what it was.
        # Todo: Try without this block, perhaps the problem doesn't exist anymore.
        if 'all_market_prices' in evaluation_kwds:
            all_market_prices = evaluation_kwds.pop('all_market_prices')
            evaluation_kwds['all_market_prices'] = dict()
            for market_name in all_market_prices.keys():
                # if market_name not in market_names:
                #     continue
                market_prices = dict()
                for date in fixing_dates:
                    market_prices[date] = all_market_prices[market_name][date]
                evaluation_kwds['all_market_prices'][market_name] = market_prices
        return evaluation_kwds
Example #7
0
def evaluate_call(call_spec, register_call_result):
    """
    Evaluates the stubbed expr identified by 'call_requirement_id'.
    """
    assert isinstance(call_spec, CallSpecification)

    evaluation_kwds = call_spec.evaluation_kwds.copy()

    # If this call has an effective present time value, use it as the 'present_time' in the evaluation_kwds.
    # This results from e.g. the Wait DSL element. Calls near the root of the expression might not have an
    # effective present time value, and the present time will be the observation time of the evaluation.

    # Evaluate the stubbed expr str.
    # - parse the expr
    try:
        # Todo: Rework this dependency. Figure out how to use alternative set of DSL classes when multiprocessing.
        from quantdsl.domain.services.parser import dsl_parse
        stubbed_module = dsl_parse(call_spec.dsl_expr_str)
    except DslSyntaxError:
        raise

    assert isinstance(stubbed_module, Module), "Parsed stubbed expr string is not a module: %s" % stubbed_module

    # - build a namespace from the dependency values
    dsl_locals = DslNamespace(call_spec.dependency_values)

    # - compile the parsed expr
    dsl_expr = stubbed_module.body[0].reduce(dsl_locals=dsl_locals, dsl_globals=DslNamespace())
    assert isinstance(dsl_expr, DslExpression), dsl_expr

    # - evaluate the compiled expr
    result_value = dsl_expr.evaluate(**evaluation_kwds)

    # - store the result
    register_call_result(call_id=call_spec.id, result_value=result_value)
Example #8
0
def generate_dependency_graph(contract_specification, call_dependencies_repo, call_dependents_repo, call_leafs_repo,
                              call_requirement_repo):

    assert isinstance(contract_specification, ContractSpecification)
    dsl_module = dsl_parse(dsl_source=contract_specification.specification)
    assert isinstance(dsl_module, Module)
    dsl_globals = DslNamespace()
    function_defs, expressions = extract_defs_and_exprs(dsl_module, dsl_globals)
    dsl_expr = expressions[0]
    assert isinstance(dsl_expr, DslExpression)
    dsl_locals = DslNamespace()

    leaf_ids = []
    all_dependents = defaultdict(list)

    # Generate stubbed call from the parsed DSL module object.
    for stub in generate_stubbed_calls(contract_specification.id, dsl_module, dsl_expr, dsl_globals, dsl_locals):
        # assert isinstance(stub, StubbedCall)

        # Register the call requirements.
        call_id = stub.call_id
        dsl_source = str(stub.dsl_expr)
        effective_present_time = stub.effective_present_time
        call_requirement = register_call_requirement(call_id, dsl_source, effective_present_time)

        # Hold onto the dsl_expr, helps in "single process" modes....
        call_requirement._dsl_expr = stub.dsl_expr
        # - put the entity directly in the cache, otherwise the entity will be regenerated when it is next accessed
        #   and the _dsl_expr will be lost.
        call_requirement_repo.add_cache(call_id, call_requirement)

        # Register the call requirements.
        dependencies = stub.requirements
        register_call_dependencies(call_id, dependencies)

        # Keep track of the leaves and the dependents.
        if len(dependencies) == 0:
            leaf_ids.append(call_id)
        else:
            for dependency_call_id in dependencies:
                all_dependents[dependency_call_id].append(call_id)

    # Register the call dependents.
    for call_id, dependents in all_dependents.items():
        register_call_dependents(call_id, dependents)
    register_call_dependents(contract_specification.id, [])

    # Generate and register the call order.
    link_id = contract_specification.id
    for call_id in generate_execution_order(leaf_ids, call_dependents_repo, call_dependencies_repo):
        register_call_link(link_id, call_id)
        link_id = call_id

    # Register the leaf ids.
    register_call_leafs(contract_specification.id, leaf_ids)
Example #9
0
def generate_dependency_graph(contract_specification, call_dependencies_repo,
                              call_dependents_repo):

    assert isinstance(contract_specification, ContractSpecification)
    dsl_module = dsl_parse(dsl_source=contract_specification.specification)
    assert isinstance(dsl_module, Module)
    dsl_globals = DslNamespace()
    function_defs, expressions = extract_defs_and_exprs(
        dsl_module, dsl_globals)
    dsl_expr = expressions[0]
    assert isinstance(dsl_expr, DslExpression)
    dsl_locals = DslNamespace()

    leaf_call_ids = []
    all_dependents = defaultdict(list)
    # Generate stubbed call from the parsed DSL module object.
    for stub in generate_stubbed_calls(contract_specification.id, dsl_module,
                                       dsl_expr, dsl_globals, dsl_locals):
        assert isinstance(stub, StubbedCall)
        call_id = stub.call_id
        dsl_source = stub.dsl_source
        effective_present_time = stub.effective_present_time
        dependencies = stub.dependencies

        # Register the call requirements.
        register_call_requirement(call_id, dsl_source, effective_present_time)

        # Register the call dependencies.
        register_call_dependencies(call_id, dependencies)

        # Keep track of the leaves and the dependents.
        if len(dependencies) == 0:
            leaf_call_ids.append(call_id)
        else:
            for dependency_call_id in dependencies:
                all_dependents[dependency_call_id].append(call_id)

    # Register the call dependents.
    for call_id, dependents in all_dependents.items():
        register_call_dependents(call_id, dependents)
    register_call_dependents(contract_specification.id, [])
    # Generate and register the call order.
    link_id = contract_specification.id
    for call_id in generate_execution_order(leaf_call_ids,
                                            call_dependents_repo,
                                            call_dependencies_repo):
        register_call_link(link_id, call_id)
        link_id = call_id
Example #10
0
def list_fixing_dates(dependency_graph_id, call_requirement_repo, call_link_repo):
    assert isinstance(call_requirement_repo, CallRequirementRepository)
    assert isinstance(call_link_repo, CallLinkRepository)
    fixing_dates = set()
    for call_id in regenerate_execution_order(dependency_graph_id, call_link_repo):

        # Get the stubbed expression.
        call_requirement = call_requirement_repo[call_id]
        assert isinstance(call_requirement, CallRequirement)
        dsl_expr = dsl_parse(call_requirement.dsl_source)

        # Find all the fixing times involved in this expression.
        for fixing_date in find_fixing_dates(dsl_expr=dsl_expr):
            fixing_dates.add(fixing_date)

    # Return a sorted list of fixing times.
    return sorted(list(fixing_dates))
Example #11
0
    def assertDslExprTypeValue(self, dsl_source, expectedDslType, expectedDslValue, **compile_kwds):
        # Assumes dsl_source is just one statement.
        dsl_module = dsl_parse(dsl_source)

        assert isinstance(dsl_module, Module)

        # Check the parsed DSL can be rendered as a string that is equal to the original source.
        self.assertEqual(str(dsl_module).strip(), dsl_source.strip())

        # Check the statement's expression type.
        dsl_expr = dsl_module.body[0]
        self.assertIsInstance(dsl_expr, expectedDslType)

        # Compile the module into an simple DSL expression object (no variables or calls to function defs).
        dsl_expr = compile_dsl_module(dsl_module, compile_kwds)

        # Evaluate the compiled expression.
        self.assertEqual(dsl_expr.evaluate(), expectedDslValue)
Example #12
0
    def assertDslExprTypeValue(self, dsl_source, expectedDslType, expectedDslValue, **compile_kwds):
        # Assumes dsl_source is just one statement.
        dsl_module = dsl_parse(dsl_source)

        assert isinstance(dsl_module, Module)

        # Check the parsed DSL can be rendered as a string that is equal to the original source.
        self.assertEqual(str(dsl_module).strip(), dsl_source.strip())

        # Check the statement's expression type.
        dsl_expr = dsl_module.body[0]
        self.assertIsInstance(dsl_expr, expectedDslType)

        # Compile the module into an simple DSL expression object (no variables or calls to function defs).
        dsl_expr = compile_dsl_module(dsl_module, compile_kwds)

        # Evaluate the compiled expression.
        self.assertEqual(dsl_expr.evaluate(), expectedDslValue)
Example #13
0
def generate_dependency_graph(contract_specification, call_dependencies_repo, call_dependents_repo):

    assert isinstance(contract_specification, ContractSpecification)
    dsl_module = dsl_parse(dsl_source=contract_specification.specification)
    assert isinstance(dsl_module, Module)
    dsl_globals = DslNamespace()
    function_defs, expressions = extract_defs_and_exprs(dsl_module, dsl_globals)
    dsl_expr = expressions[0]
    assert isinstance(dsl_expr, DslExpression)
    dsl_locals = DslNamespace()

    leaf_call_ids = []
    all_dependents = defaultdict(list)
    # Generate stubbed call from the parsed DSL module object.
    for stub in generate_stubbed_calls(contract_specification.id, dsl_module, dsl_expr, dsl_globals, dsl_locals):
        assert isinstance(stub, StubbedCall)
        call_id = stub.call_id
        dsl_source = stub.dsl_source
        effective_present_time = stub.effective_present_time
        dependencies = stub.dependencies

        # Register the call requirements.
        register_call_requirement(call_id, dsl_source, effective_present_time)

        # Register the call dependencies.
        register_call_dependencies(call_id, dependencies)

        # Keep track of the leaves and the dependents.
        if len(dependencies) == 0:
            leaf_call_ids.append(call_id)
        else:
            for dependency_call_id in dependencies:
                all_dependents[dependency_call_id].append(call_id)

    # Register the call dependents.
    for call_id, dependents in all_dependents.items():
        register_call_dependents(call_id, dependents)
    register_call_dependents(contract_specification.id, [])
    # Generate and register the call order.
    link_id = contract_specification.id
    for call_id in generate_execution_order(leaf_call_ids, call_dependents_repo, call_dependencies_repo):
        register_call_link(link_id, call_id)
        link_id = call_id
Example #14
0
    def generate_contract_valuation(self, dependency_graph_id, market_simulation):
        assert isinstance(dependency_graph_id, six.string_types), dependency_graph_id
        assert isinstance(market_simulation, MarketSimulation)
        v = self.register_contract_valuation(dependency_graph_id)

        for call_id in regenerate_execution_order(dependency_graph_id, self.call_link_repo):

            call = self.call_requirement_repo[call_id]
            assert isinstance(call, CallRequirement)

            # Evaluate the call requirement.
            dependency_values = get_dependency_values(call_id, self.call_dependencies_repo, self.call_result_repo)

            # - parse the expr
            stubbed_module = dsl_parse(call.dsl_source)

            assert isinstance(stubbed_module, Module), "Parsed stubbed expr string is not a module: %s" % stubbed_module

            # - build a namespace from the dependency values
            dsl_locals = DslNamespace(dependency_values)

            # - compile the parsed expr
            dsl_expr = stubbed_module.body[0].reduce(dsl_locals=dsl_locals, dsl_globals=DslNamespace())
            assert isinstance(dsl_expr, DslExpression), dsl_expr

            # - evaluate the compiled expr
            first_market_name = market_simulation.market_names[0] if market_simulation.market_names else None
            evaluation_kwds = {
                'simulated_price_repo': self.simulated_price_repo,
                'simulation_id': market_simulation.id,
                'interest_rate': market_simulation.interest_rate,
                'present_time': call.effective_present_time or market_simulation.observation_date,
                'first_market_name': first_market_name,
            }
            result_value = dsl_expr.evaluate(**evaluation_kwds)

            # - store the result
            register_call_result(call_id=call_id, result_value=result_value)
Example #15
0
    def assertDslExprTypeValue(self, dsl_source, expectedDslType, expectedDslValue, **compile_kwds):
        # Assumes dsl_source is just one statement.
        dsl_module = dsl_parse(dsl_source)

        assert isinstance(dsl_module, Module)

        # Check the parsed DSL can be rendered as a string that is equal to the original source.
        self.assertEqual(str(dsl_module), dsl_source.strip())

        # Assume this test is dealing with modules that have one statement only.
        dsl_expr = dsl_module.body[0]

        # Check expression type.
        assert isinstance(dsl_expr, DslExpression)
        self.assertIsInstance(dsl_expr, expectedDslType)

        # Compile the module into a simple DSL expression object (no variables or calls to function defs).
        dsl_expr = dsl_expr.substitute_names(DslNamespace(compile_kwds))

        # Evaluate the compiled expression.
        dsl_value = dsl_expr.evaluate()

        self.assertEqual(dsl_value, expectedDslValue)
Example #16
0
    def assertDslExprTypeValue(self, dsl_source, expectedDslType,
                               expectedDslValue, **compile_kwds):
        # Assumes dsl_source is just one statement.
        dsl_module = dsl_parse(dsl_source)

        assert isinstance(dsl_module, Module)

        # Check the parsed DSL can be rendered as a string that is equal to the original source.
        self.assertEqual(str(dsl_module), dsl_source.strip())

        # Assume this test is dealing with modules that have one statement only.
        dsl_expr = dsl_module.body[0]

        # Check expression type.
        assert isinstance(dsl_expr, DslExpression)
        self.assertIsInstance(dsl_expr, expectedDslType)

        # Compile the module into a simple DSL expression object (no variables or calls to function defs).
        dsl_expr = dsl_expr.substitute_names(DslNamespace(compile_kwds))

        # Evaluate the compiled expression.
        dsl_value = dsl_expr.evaluate()

        self.assertEqual(dsl_value, expectedDslValue)
Example #17
0
def compute_call_result(contract_valuation,
                        call_requirement,
                        market_simulation,
                        perturbation_dependencies,
                        call_dependencies_repo,
                        call_result_repo,
                        simulated_price_repo,
                        perturbation_dependencies_repo,
                        simulation_requirements,
                        compute_pool=None):
    """
    Parses, compiles and evaluates a call requirement.
    """
    # assert isinstance(contract_valuation, ContractValuation), contract_valuation
    assert isinstance(call_requirement, CallRequirement), call_requirement
    # assert isinstance(market_simulation, MarketSimulation), market_simulation
    # assert isinstance(call_dependencies_repo, CallDependenciesRepository), call_dependencies_repo
    # assert isinstance(call_result_repo, CallResultRepository)
    # assert isinstance(simulated_price_dict, SimulatedPriceRepository)

    # Todo: Put getting the dependency values in a separate thread, and perhaps make each call a separate thread.
    # Parse the DSL source into a DSL module object (composite tree of objects that provide the DSL semantics).
    if call_requirement._dsl_expr is not None:
        dsl_expr = call_requirement._dsl_expr
    else:
        dsl_module = dsl_parse(call_requirement.dsl_source)
        dsl_expr = dsl_module.body[0]

    # assert isinstance(dsl_module, Module), "Parsed stubbed expr string is not a module: %s" % dsl_module

    present_time = call_requirement.effective_present_time or market_simulation.observation_date

    simulated_value_dict = {}
    # market_simulation.dependencies

    #
    # all_fixing_dates = set([present_time] + list_fixing_dates(dsl_expr))
    # market_dependencies = perturbation_dependencies_repo[call_requirement.id]
    # assert isinstance(market_dependencies, PerturbationDependencies)
    # all_delivery_points = market_dependencies.dependencies
    # for fixing_date in all_fixing_dates:
    #     for delivery_point in all_delivery_points:
    #         market_name = delivery_point[0]
    #         delivery_date = delivery_point[1]
    #         simulation_id = contract_valuation.market_simulation_id
    #         price_id = make_simulated_price_id(simulation_id, market_name, fixing_date, delivery_date)
    #         simulated_price = simulated_price_dict[price_id]
    #         # assert isinstance(simulated_price, SimulatedPrice)
    #         # assert isinstance(simulated_price.value, scipy.ndarray)
    #         simulated_value_dict[price_id] = simulated_price.value

    simulation_id = contract_valuation.market_simulation_id

    first_commodity_name = None

    for simulation_requirement in simulation_requirements:
        (commodity_name, fixing_date, delivery_date) = simulation_requirement
        if first_commodity_name is None:
            first_commodity_name = commodity_name
        price_id = make_simulated_price_id(simulation_id, commodity_name,
                                           fixing_date, delivery_date)
        simulated_price = simulated_price_repo[price_id]
        simulated_value_dict[price_id] = simulated_price.value

    # Get all the call results depended on by this call.
    dependency_results = get_dependency_results(
        contract_valuation_id=contract_valuation.id,
        call_id=call_requirement.id,
        dependencies_repo=call_dependencies_repo,
        result_repo=call_result_repo,
    )

    # Compute the call result.
    if compute_pool is None:
        result_value, perturbed_values = evaluate_dsl_expr(
            dsl_expr, first_commodity_name, market_simulation.id,
            market_simulation.interest_rate, present_time,
            simulated_value_dict, perturbation_dependencies.dependencies,
            dependency_results, market_simulation.path_count)
    else:
        assert isinstance(compute_pool, Pool)
        async_result = compute_pool.apply_async(
            evaluate_dsl_expr,
            args=(dsl_expr, first_commodity_name, market_simulation.id,
                  market_simulation.interest_rate, present_time,
                  simulated_value_dict, perturbation_dependencies.dependencies,
                  dependency_results, market_simulation.path_count),
        )
        gevent.sleep(0.0001)
        result_value, perturbed_values = async_result.get()

    # Return the result.
    return result_value, perturbed_values
Example #18
0
def generate_dependency_graph(contract_specification,
                              call_dependencies_repo,
                              call_dependents_repo,
                              call_requirement_repo,
                              dsl_classes=None):
    assert isinstance(contract_specification, ContractSpecification)
    dsl_module = dsl_parse(
        dsl_source=contract_specification.source_code,
        dsl_classes=dsl_classes,
    )
    assert isinstance(dsl_module, Module)
    dsl_globals = dsl_module.namespace.copy()
    function_defs, expressions = extract_defs_and_exprs(
        dsl_module, dsl_globals)
    dsl_expr = expressions[0]
    assert isinstance(dsl_expr, DslExpression)
    dsl_locals = DslNamespace()

    leaf_ids = []
    all_dependents = defaultdict(list)

    # Generate stubbed call from the parsed DSL module object.
    for stubed_call in generate_stubbed_calls(
            contract_specification.id, dsl_expr, dsl_globals, dsl_locals,
            contract_specification.observation_date):
        # assert isinstance(stub, StubbedCall)

        # Estimate the cost of evaluating this expression.
        estimated_cost = stubed_call.dsl_expr.cost_expression()

        # Register the call requirements.
        call_id = stubed_call.call_id
        dsl_source = str(stubed_call.dsl_expr)
        present_time = stubed_call.present_time
        call_requirement = register_call_requirement(
            call_id=call_id,
            dsl_source=dsl_source,
            present_time=present_time,
            contract_specification_id=contract_specification.id,
            cost=estimated_cost,
        )

        # Hold onto the dsl_expr, helps in "single process" modes.
        # - put the entity directly in the cache, otherwise the entity will be
        # regenerated when it is next accessed and the _dsl_expr will be "lost"
        call_requirement._dsl_expr = stubed_call.dsl_expr
        call_requirement_repo.add_cache(call_id, call_requirement)

        # Register the call dependencies (things needed by this call).
        dependencies = stubed_call.requirements
        register_call_dependencies(call_id, dependencies)

        # Keep track of the leaves and the dependents.
        if len(dependencies) == 0:
            leaf_ids.append(call_id)
        else:
            for dependency_call_id in dependencies:
                all_dependents[dependency_call_id].append(call_id)

    # Register the call dependents.
    for call_id, dependents in all_dependents.items():
        register_call_dependents(call_id, dependents)
    register_call_dependents(contract_specification.id, [])

    # Generate and register the call order.
    link_id = contract_specification.id
    for call_id in generate_execution_order(leaf_ids, call_dependents_repo,
                                            call_dependencies_repo):
        register_call_link(link_id, call_id)
        link_id = call_id

    # Register the leaf ids.
    register_call_leafs(contract_specification.id, leaf_ids)
Example #19
0
 def test_empty_string(self):
     # Empty string can be parsed as a module, but not compiled into an expression, or evaluated.
     self.assertTrue(isinstance(dsl_parse(""), Module))
     self.assertRaises(DslSyntaxError, dsl_compile, "")
     self.assertRaises(DslSyntaxError, dsl_eval, "")
Example #20
0
def generate_dependency_graph(contract_specification, call_dependencies_repo, call_dependents_repo,
                              call_requirement_repo, dsl_classes=None):
    assert isinstance(contract_specification, ContractSpecification)
    dsl_module = dsl_parse(
        dsl_source=contract_specification.source_code,
        dsl_classes=dsl_classes,
    )
    assert isinstance(dsl_module, Module)
    dsl_globals = dsl_module.namespace.copy()
    function_defs, expressions = extract_defs_and_exprs(dsl_module, dsl_globals)
    dsl_expr = expressions[0]
    assert isinstance(dsl_expr, DslExpression)
    dsl_locals = DslNamespace()

    leaf_ids = []
    all_dependents = defaultdict(list)

    # Generate stubbed call from the parsed DSL module object.
    for stubed_call in generate_stubbed_calls(contract_specification.id, dsl_expr, dsl_globals, dsl_locals,
                                              contract_specification.observation_date):
        # assert isinstance(stub, StubbedCall)

        # Estimate the cost of evaluating this expression.
        estimated_cost = stubed_call.dsl_expr.cost_expression()

        # Register the call requirements.
        call_id = stubed_call.call_id
        dsl_source = str(stubed_call.dsl_expr)
        present_time = stubed_call.present_time
        call_requirement = register_call_requirement(
            call_id=call_id,
            dsl_source=dsl_source,
            present_time=present_time,
            contract_specification_id=contract_specification.id,
            cost=estimated_cost,
        )

        # Hold onto the dsl_expr, helps in "single process" modes.
        # - put the entity directly in the cache, otherwise the entity will be
        # regenerated when it is next accessed and the _dsl_expr will be "lost"
        call_requirement._dsl_expr = stubed_call.dsl_expr
        call_requirement_repo.add_cache(call_id, call_requirement)

        # Register the call dependencies (things needed by this call).
        dependencies = stubed_call.requirements
        register_call_dependencies(call_id, dependencies)

        # Keep track of the leaves and the dependents.
        if len(dependencies) == 0:
            leaf_ids.append(call_id)
        else:
            for dependency_call_id in dependencies:
                all_dependents[dependency_call_id].append(call_id)

    # Register the call dependents.
    for call_id, dependents in all_dependents.items():
        register_call_dependents(call_id, dependents)
    register_call_dependents(contract_specification.id, [])

    # Generate and register the call order.
    link_id = contract_specification.id
    for call_id in generate_execution_order(leaf_ids, call_dependents_repo, call_dependencies_repo):
        register_call_link(link_id, call_id)
        link_id = call_id

    # Register the leaf ids.
    register_call_leafs(contract_specification.id, leaf_ids)
Example #21
0
 def test_empty_string(self):
     self.assertTrue(isinstance(dsl_parse(""), Module))
     self.assertRaises(DslSyntaxError, dsl_compile, "")
     self.assertRaises(DslSyntaxError, dsl_eval, "")
Example #22
0
def identify_simulation_requirements(contract_specification_id, call_requirement_repo, call_link_repo,
                                     call_dependencies_repo, observation_date, requirements, periodisation=None):
    assert isinstance(call_requirement_repo, CallRequirementRepository)
    assert isinstance(call_link_repo, CallLinkRepository)

    all_perturbation_dependencies = {}

    call_requirements = []

    for call_id in regenerate_execution_order(contract_specification_id, call_link_repo):

        # Get the stubbed expression.
        call_requirement = call_requirement_repo[call_id]
        assert isinstance(call_requirement, CallRequirement)

        if call_requirement._dsl_expr is not None:
            dsl_expr = call_requirement._dsl_expr
        else:
            dsl_module = dsl_parse(call_requirement.dsl_source)
            dsl_expr = dsl_module.body[0]
            call_requirement._dsl_expr = dsl_expr
        assert isinstance(dsl_expr, DslObject), dsl_expr

        call_requirements.append(call_requirement)

    all_market_names = set()
    for call_requirement in call_requirements:
        dsl_expr = call_requirement._dsl_expr
        for market in dsl_expr.find_instances(AbstractMarket):
            assert isinstance(market.commodity_name, six.string_types)
            all_market_names.add(market.commodity_name)

    for call_requirement in call_requirements:
        dsl_expr = call_requirement._dsl_expr

        call_id = call_requirement.id

        # Todo: Consolidate 'date' attributes to be a single element (rather than a possibly long sum expression).

        # Identify this call's requirements for simulated prices.
        simulation_requirements = set()
        present_time = call_requirement.present_time
        dsl_expr.identify_price_simulation_requirements(
            requirements=simulation_requirements,
            present_time=present_time,
            observation_date=observation_date,
            periodisation=periodisation,
            all_market_names=all_market_names,
        )

        # Register the simulation requirements for each call (needed during evaluation).
        register_simulated_price_requirements(call_id, list(simulation_requirements))

        # Update the simulation requirements (needed for the market simulation).
        requirements.update(simulation_requirements)

        # Identify this call's perturbation dependencies.
        perturbation_dependencies = set()
        dsl_expr.identify_perturbation_dependencies(
            dependencies=perturbation_dependencies,
            present_time=present_time,
            periodisation=periodisation,
        )

        # Add the expression's perturbation dependencies to the perturbation dependencies of its call dependencies.
        call_dependencies = call_dependencies_repo[call_id]
        assert isinstance(call_dependencies, CallDependencies), call_dependencies
        for dependency_id in call_dependencies.dependencies:
            dependency_perturbation_dependencies = all_perturbation_dependencies[dependency_id]
            perturbation_dependencies.update(dependency_perturbation_dependencies)
        # Register the perturbation dependencies in the repo (needed when evaluating the call).
        register_perturbation_dependencies(call_id, list(perturbation_dependencies))

        # Save the perturbation dependencies for this call, so they are available for the dependent calls.
        all_perturbation_dependencies[call_id] = perturbation_dependencies
Example #23
0
def list_market_names(contract_specification):
    assert isinstance(contract_specification, ContractSpecification)
    dsl_module = dsl_parse(contract_specification.specification)
    return list(find_market_names(dsl_expr=dsl_module))
Example #24
0
 def test_empty_string(self):
     self.assertTrue(isinstance(dsl_parse(""), Module))
     self.assertRaises(DslSyntaxError, dsl_compile, "")
     self.assertRaises(DslSyntaxError, dsl_eval, "")
Example #25
0
def identify_simulation_requirements(contract_specification_id,
                                     call_requirement_repo,
                                     call_link_repo,
                                     call_dependencies_repo,
                                     observation_date,
                                     requirements,
                                     periodisation=None):
    assert isinstance(call_requirement_repo, CallRequirementRepository)
    assert isinstance(call_link_repo, CallLinkRepository)

    all_perturbation_dependencies = {}

    call_requirements = []

    for call_id in regenerate_execution_order(contract_specification_id,
                                              call_link_repo):

        # Get the stubbed expression.
        call_requirement = call_requirement_repo[call_id]
        assert isinstance(call_requirement, CallRequirement)

        if call_requirement._dsl_expr is not None:
            dsl_expr = call_requirement._dsl_expr
        else:
            dsl_module = dsl_parse(call_requirement.dsl_source)
            dsl_expr = dsl_module.body[0]
            call_requirement._dsl_expr = dsl_expr
        assert isinstance(dsl_expr, DslObject), dsl_expr

        call_requirements.append(call_requirement)

    all_market_names = set()
    for call_requirement in call_requirements:
        dsl_expr = call_requirement._dsl_expr
        for market in dsl_expr.find_instances(AbstractMarket):
            assert isinstance(market.commodity_name, six.string_types)
            all_market_names.add(market.commodity_name)

    for call_requirement in call_requirements:
        dsl_expr = call_requirement._dsl_expr

        call_id = call_requirement.id

        # Todo: Consolidate 'date' attributes to be a single element (rather than a possibly long sum expression).

        # Identify this call's requirements for simulated prices.
        simulation_requirements = set()
        present_time = call_requirement.present_time
        dsl_expr.identify_price_simulation_requirements(
            requirements=simulation_requirements,
            present_time=present_time,
            observation_date=observation_date,
            periodisation=periodisation,
            all_market_names=all_market_names,
        )

        # Register the simulation requirements for each call (needed during evaluation).
        register_simulated_price_requirements(call_id,
                                              list(simulation_requirements))

        # Update the simulation requirements (needed for the market simulation).
        requirements.update(simulation_requirements)

        # Identify this call's perturbation dependencies.
        perturbation_dependencies = set()
        dsl_expr.identify_perturbation_dependencies(
            dependencies=perturbation_dependencies,
            present_time=present_time,
            periodisation=periodisation,
        )

        # Add the expression's perturbation dependencies to the perturbation dependencies of its call dependencies.
        call_dependencies = call_dependencies_repo[call_id]
        assert isinstance(call_dependencies,
                          CallDependencies), call_dependencies
        for dependency_id in call_dependencies.dependencies:
            dependency_perturbation_dependencies = all_perturbation_dependencies[
                dependency_id]
            perturbation_dependencies.update(
                dependency_perturbation_dependencies)
        # Register the perturbation dependencies in the repo (needed when evaluating the call).
        register_perturbation_dependencies(call_id,
                                           list(perturbation_dependencies))

        # Save the perturbation dependencies for this call, so they are available for the dependent calls.
        all_perturbation_dependencies[call_id] = perturbation_dependencies
Example #26
0
 def test_empty_string(self):
     # Empty string can be parsed as a module, but not compiled into an expression, or evaluated.
     self.assertTrue(isinstance(dsl_parse(""), Module))
     self.assertRaises(DslSyntaxError, dsl_compile, "")
     self.assertRaises(DslSyntaxError, dsl_eval, "")