def compute_call_result(contract_valuation, call_requirement, market_simulation, perturbation_dependencies,
                        call_dependencies_repo, call_result_repo, simulated_price_repo, simulation_requirements,
                        is_double_sided_deltas):
    """
    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)

    present_time = call_requirement.present_time

    simulated_value_dict = {}

    simulation_id = contract_valuation.market_simulation_id

    involved_market_names = set()

    for simulation_requirement in simulation_requirements:
        (commodity_name, fixing_date, delivery_date) = simulation_requirement

        # Accumulate involved market names (needed in Choice for regressions).
        involved_market_names.add(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,
    )

    # Accumulate market names from dependency results.
    for dependency_result in dependency_results.values():
        assert isinstance(dependency_result, CallResult), dependency_result
        involved_market_names.update(dependency_result.involved_market_names)

    result_value, perturbed_values = evaluate_dsl_expr(call_requirement._dsl_expr,
                                                       market_simulation.id,
                                                       market_simulation.interest_rate, present_time,
                                                       simulated_value_dict,
                                                       perturbation_dependencies.dependencies,
                                                       dependency_results,
                                                       market_simulation.path_count,
                                                       market_simulation.perturbation_factor,
                                                       contract_valuation.periodisation,
                                                       call_requirement.cost,
                                                       market_simulation.observation_date,
                                                       is_double_sided_deltas,
                                                       involved_market_names)

    # Return the result.
    return result_value, perturbed_values, involved_market_names
def compute_call_result(contract_valuation, call_requirement,
                        market_simulation, perturbation_dependencies,
                        call_dependencies_repo, call_result_repo,
                        simulated_price_repo, simulation_requirements,
                        is_double_sided_deltas):
    """
    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)

    present_time = call_requirement.present_time

    simulated_value_dict = {}

    simulation_id = contract_valuation.market_simulation_id

    involved_market_names = set()

    for simulation_requirement in simulation_requirements:
        (commodity_name, fixing_date, delivery_date) = simulation_requirement

        # Accumulate involved market names (needed in Choice for regressions).
        involved_market_names.add(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,
    )

    # Accumulate market names from dependency results.
    for dependency_result in dependency_results.values():
        assert isinstance(dependency_result, CallResult), dependency_result
        involved_market_names.update(dependency_result.involved_market_names)

    result_value, perturbed_values = evaluate_dsl_expr(
        call_requirement._dsl_expr, market_simulation.id,
        market_simulation.interest_rate, present_time, simulated_value_dict,
        perturbation_dependencies.dependencies, dependency_results,
        market_simulation.path_count, market_simulation.perturbation_factor,
        contract_valuation.periodisation, call_requirement.cost,
        market_simulation.observation_date, is_double_sided_deltas,
        involved_market_names)

    # Return the result.
    return result_value, perturbed_values, involved_market_names
    def test_register_market_simulation(self):
        # Set up the market calibration.
        price_process_name = DEFAULT_PRICE_PROCESS_NAME
        calibration_params = {
            'market': ['#1', '#2'],
            'sigma': [0.1, 0.2],
            'curve': {
                '#1': [
                    ('2011-1-1', 10),
                ],
                '#2': [
                    ('2011-1-1', 20),
                ],
            },
            'rho': [
                [1.0, 0.5],
                [0.5, 1.0],
            ],
        }
        market_calibration = self.app.register_market_calibration(price_process_name, calibration_params)

        # Create a market simulation for a list of markets and fixing times.
        commodity_names = ['#%d' % (i+1) for i in range(self.NUMBER_MARKETS)]
        fixing_dates = [datetime.datetime(2011, 1, 1) + datetime.timedelta(days=i) for i in range(self.NUMBER_DAYS)]
        observation_date = fixing_dates[0]
        simulation_requirements = []
        for commodity_name in commodity_names:
            for fixing_date in fixing_dates:
                simulation_requirements.append((commodity_name, fixing_date, fixing_date))
        path_count = self.PATH_COUNT

        market_simulation = self.app.register_market_simulation(
            market_calibration_id=market_calibration.id,
            requirements=simulation_requirements,
            observation_date=observation_date,
            path_count=path_count,
            interest_rate=2.5,
        )

        assert isinstance(market_simulation, MarketSimulation)
        assert market_simulation.id
        market_simulation = self.app.market_simulation_repo[market_simulation.id]
        assert isinstance(market_simulation, MarketSimulation)
        self.assertEqual(market_simulation.market_calibration_id, market_calibration.id)
        # self.assertEqual(market_simulation.requirements[0], ['#1', '#2'])
        # self.assertEqual(market_simulation.fixing_dates, [datetime.date(2011, 1, i) for i in range(2, 6)])
        self.assertEqual(market_simulation.observation_date, datetime.datetime(2011, 1, 1))
        self.assertEqual(market_simulation.path_count, self.PATH_COUNT)

        # Check there are simulated prices for all the requirements.
        for requirement in simulation_requirements:
            commodity_name = requirement[0]
            fixing_date = requirement[1]
            delivery_date = requirement[2]
            simulated_price_id = make_simulated_price_id(market_simulation.id, commodity_name, fixing_date, delivery_date)
            simulated_price = self.app.simulated_price_repo[simulated_price_id]
            self.assertIsInstance(simulated_price, SimulatedPrice)
            self.assertTrue(simulated_price.value.mean())
Example #4
0
    def test_register_simulated_price(self):

        price_time = datetime.datetime(2011, 1, 1)
        price_value = numpy.array([1.1, 1.2, 1.367345987359734598734598723459872345987235698237459862345])
        simulation_id = create_uuid4()
        self.assertRaises(KeyError, self.app.simulated_price_repo.__getitem__, simulation_id)

        price = register_simulated_price(simulation_id, '#1', price_time, price_value)

        assert isinstance(price, SimulatedPrice), price
        assert price.id
        price = self.app.simulated_price_repo[make_simulated_price_id(simulation_id, '#1', price_time)]
        assert isinstance(price, SimulatedPrice)
        numpy.testing.assert_equal(price.value, price_value)
Example #5
0
    def test_register_market_simulation(self):
        # Set up the market calibration.
        price_process_name = DEFAULT_PRICE_PROCESS_NAME
        calibration_params = {
            '#1-LAST-PRICE': 10,
            '#2-LAST-PRICE': 20,
            '#1-ACTUAL-HISTORICAL-VOLATILITY': 10,
            '#2-ACTUAL-HISTORICAL-VOLATILITY': 20,
            '#1-#2-CORRELATION': 0.5,
        }
        market_calibration = self.app.register_market_calibration(price_process_name, calibration_params)

        # Create a market simulation for a list of markets and fixing times.
        commodity_names = ['#%d' % (i+1) for i in range(self.NUMBER_MARKETS)]
        fixing_dates = [datetime.datetime(2011, 1, 1) + datetime.timedelta(days=i) for i in range(self.NUMBER_DAYS)]
        observation_date = fixing_dates[0]
        simulation_requirements = []
        for commodity_name in commodity_names:
            for fixing_date in fixing_dates:
                simulation_requirements.append((commodity_name, fixing_date, fixing_date))
        path_count = self.PATH_COUNT

        market_simulation = self.app.register_market_simulation(
            market_calibration_id=market_calibration.id,
            requirements=simulation_requirements,
            observation_date=observation_date,
            path_count=path_count,
            interest_rate=2.5,
        )

        assert isinstance(market_simulation, MarketSimulation)
        assert market_simulation.id
        market_simulation = self.app.market_simulation_repo[market_simulation.id]
        assert isinstance(market_simulation, MarketSimulation)
        self.assertEqual(market_simulation.market_calibration_id, market_calibration.id)
        # self.assertEqual(market_simulation.requirements[0], ['#1', '#2'])
        # self.assertEqual(market_simulation.fixing_dates, [datetime.date(2011, 1, i) for i in range(2, 6)])
        self.assertEqual(market_simulation.observation_date, datetime.datetime(2011, 1, 1))
        self.assertEqual(market_simulation.path_count, self.PATH_COUNT)

        # Check there are simulated prices for all the requirements.
        for requirement in simulation_requirements:
            commodity_name = requirement[0]
            fixing_date = requirement[1]
            delivery_date = requirement[2]
            simulated_price_id = make_simulated_price_id(market_simulation.id, commodity_name, fixing_date, delivery_date)
            simulated_price = self.app.simulated_price_repo[simulated_price_id]
            self.assertIsInstance(simulated_price, SimulatedPrice)
            self.assertTrue(simulated_price.value.mean())
Example #6
0
    def test_register_market_simulation(self):
        # Set up the market calibration.
        price_process_name = DEFAULT_PRICE_PROCESS_NAME
        calibration_params = {
            '#1-LAST-PRICE': 10,
            '#2-LAST-PRICE': 20,
            '#1-ACTUAL-HISTORICAL-VOLATILITY': 10,
            '#2-ACTUAL-HISTORICAL-VOLATILITY': 20,
            '#1-#2-CORRELATION': 0.5,
        }
        market_calibration = self.app.register_market_calibration(price_process_name, calibration_params)

        # Create a market simulation for a list of markets and fixing times.
        market_names = ['#%d' % (i+1) for i in range(self.NUMBER_MARKETS)]
        date_range = [datetime.date(2011, 1, 1) + datetime.timedelta(days=i) for i in range(self.NUMBER_DAYS)]
        fixing_dates = date_range[1:]
        observation_date = date_range[0]
        path_count = self.PATH_COUNT

        market_simulation = self.app.register_market_simulation(
            market_calibration_id=market_calibration.id,
            market_names=market_names,
            fixing_dates=fixing_dates,
            observation_date=observation_date,
            path_count=path_count,
            interest_rate=2.5,
        )

        assert isinstance(market_simulation, MarketSimulation)
        assert market_simulation.id
        market_simulation = self.app.market_simulation_repo[market_simulation.id]
        assert isinstance(market_simulation, MarketSimulation)
        self.assertEqual(market_simulation.market_calibration_id, market_calibration.id)
        self.assertEqual(market_simulation.market_names, ['#1', '#2'])
        self.assertEqual(market_simulation.fixing_dates, [datetime.date(2011, 1, i) for i in range(2, 6)])
        self.assertEqual(market_simulation.observation_date, datetime.date(2011, 1, 1))
        self.assertEqual(market_simulation.path_count, self.PATH_COUNT)

        # Check there are simulated prices for all markets at all fixing times.
        for market_name in market_names:
            for fixing_date in fixing_dates:
                simulated_price_id = make_simulated_price_id(market_simulation.id, market_name, fixing_date)
                simulated_price = self.app.simulated_price_repo[simulated_price_id]
                self.assertIsInstance(simulated_price, SimulatedPrice)
                self.assertTrue(simulated_price.value.mean())
Example #7
0
    def assert_contract_value(self,
                              specification,
                              expected_value,
                              expected_deltas=None,
                              expected_call_count=None):
        # Register the specification (creates call dependency graph).
        contract_specification = self.app.register_contract_specification(
            specification=specification)

        # Check the call count (the number of nodes of the call dependency graph).
        call_count = len(
            list(
                regenerate_execution_order(contract_specification.id,
                                           self.app.call_link_repo)))

        if expected_call_count is not None:
            self.assertEqual(call_count, expected_call_count)

        # Generate the market simulation.
        market_simulation = self.setup_market_simulation(
            contract_specification)

        # Generate the contract valuation ID.
        contract_valuation_id = create_contract_valuation_id()
        call_result_id = make_call_result_id(contract_valuation_id,
                                             contract_specification.id)

        # Listen for the call result, if possible.
        # Todo: Listen for results, rather than polling for results - there will be less lag.
        # call_result_listener = None

        # Start the contract valuation.
        self.app.start_contract_valuation(contract_valuation_id,
                                          contract_specification.id,
                                          market_simulation)

        # # Get the call result.
        # if call_result_listener:
        #     call_result_listener.wait()

        main_result = self.get_result(call_result_id, call_count)

        # Check the call result.
        assert isinstance(main_result, CallResult)
        self.assertAlmostEqual(self.scalar(main_result.result_value),
                               expected_value,
                               places=2)

        if expected_deltas is None:
            return

        # Generate the contract valuation deltas.
        assert isinstance(market_simulation, MarketSimulation)
        for perturbation in expected_deltas.keys():

            # Compute the delta.
            if perturbation not in main_result.perturbed_values:
                self.fail("There isn't a perturbed value for '{}': {}"
                          "".format(perturbation,
                                    list(main_result.perturbed_values.keys())))

            perturbed_value = main_result.perturbed_values[perturbation].mean()
            market_calibration = self.app.market_calibration_repo[
                market_simulation.market_calibration_id]
            assert isinstance(market_calibration, MarketCalibration)
            commodity_name = perturbation.split('-')[0]
            simulated_price_id = make_simulated_price_id(
                market_simulation.id, commodity_name,
                market_simulation.observation_date,
                market_simulation.observation_date)
            simulated_price = self.app.simulated_price_repo[simulated_price_id]

            dy = perturbed_value - main_result.result_value
            dx = Market.PERTURBATION_FACTOR * simulated_price.value
            contract_delta = dy / dx

            # Check the delta.
            actual_value = contract_delta.mean()
            expected_value = expected_deltas[perturbation]
            error_msg = "{}: {} != {}".format(perturbation, actual_value,
                                              expected_value)
            self.assertAlmostEqual(actual_value,
                                   expected_value,
                                   places=2,
                                   msg=error_msg)
Example #8
0
 def __getitem__(self, dt):
     assert isinstance(dt, datetime.datetime)
     app = get_quantdsl_app()
     return app.simulated_price_repo[make_simulated_price_id(self.simulation_id, self.name, dt)]
Example #9
0
    def read_results(self, evaluation):
        assert isinstance(evaluation, ContractValuation)

        market_simulation = self.market_simulation_repo[
            evaluation.market_simulation_id]

        call_result_id = make_call_result_id(
            evaluation.id, evaluation.contract_specification_id)
        call_result = self.call_result_repo[call_result_id]

        fair_value = call_result.result_value

        perturbation_names = call_result.perturbed_values.keys()
        perturbation_names = [
            i for i in perturbation_names if not i.startswith('-')
        ]
        perturbation_names = sorted(
            perturbation_names,
            key=lambda x: [int(i) for i in x.split('-')[1:]])

        periods = []
        for perturbation_name in perturbation_names:

            perturbed_value = call_result.perturbed_values[perturbation_name]
            if evaluation.is_double_sided_deltas:
                perturbed_value_negative = call_result.perturbed_values[
                    '-' + perturbation_name]
            else:
                perturbed_value_negative = None
            # Assumes format: NAME-YEAR-MONTH
            perturbed_name_split = perturbation_name.split('-')
            market_name = perturbed_name_split[0]

            if market_name == perturbation_name:
                simulated_price_id = make_simulated_price_id(
                    market_simulation.id, market_name,
                    market_simulation.observation_date,
                    market_simulation.observation_date)

                simulated_price = self.simulated_price_repo[simulated_price_id]
                price = simulated_price.value
                if evaluation.is_double_sided_deltas:
                    dy = perturbed_value - perturbed_value_negative
                else:
                    dy = perturbed_value - fair_value

                dx = market_simulation.perturbation_factor * price
                if evaluation.is_double_sided_deltas:
                    dx *= 2

                delta = dy / dx

                hedge_units = -delta
                hedge_cost = hedge_units * price
                periods.append({
                    'market_name': market_name,
                    'delivery_date': None,
                    'delta': delta,
                    'perturbation_name': perturbation_name,
                    'hedge_units': hedge_units,
                    'price_simulated': price,
                    'price_discounted': price,
                    'hedge_cost': hedge_cost,
                })

            elif len(perturbed_name_split) > 2:
                year = int(perturbed_name_split[1])
                month = int(perturbed_name_split[2])
                if len(perturbed_name_split) > 3:
                    day = int(perturbed_name_split[3])
                    delivery_date = datetime.date(year, month, day)
                    simulated_price_id = make_simulated_price_id(
                        market_simulation.id, market_name, delivery_date,
                        delivery_date)
                    simulated_price = self.simulated_price_repo[
                        simulated_price_id]
                    simulated_price_value = simulated_price.value

                else:
                    delivery_date = datetime.date(year, month, 1)
                    sum_simulated_prices = 0
                    count_simulated_prices = 0
                    for i in range(1, 32):
                        try:
                            _delivery_date = datetime.date(year, month, i)
                        except ValueError:
                            continue
                        else:
                            simulated_price_id = make_simulated_price_id(
                                market_simulation.id, market_name,
                                _delivery_date, _delivery_date)
                            try:
                                simulated_price = self.simulated_price_repo[
                                    simulated_price_id]
                            except KeyError:
                                pass
                            else:
                                sum_simulated_prices += simulated_price.value
                                count_simulated_prices += 1
                    assert count_simulated_prices, "Can't find any simulated prices for {}-{}".format(
                        year, month)
                    simulated_price_value = sum_simulated_prices / count_simulated_prices

                # Assume present time of perturbed values is observation date.
                if evaluation.is_double_sided_deltas:
                    dy = perturbed_value - perturbed_value_negative
                else:
                    dy = perturbed_value - fair_value

                discount_rate = discount(
                    value=1,
                    present_date=market_simulation.observation_date,
                    value_date=delivery_date,
                    interest_rate=market_simulation.interest_rate)

                discounted_simulated_price_value = simulated_price_value * discount_rate

                dx = market_simulation.perturbation_factor * simulated_price_value
                if evaluation.is_double_sided_deltas:
                    dx *= 2
                delta = dy / dx

                # The delta of a forward contract at the observation date
                # is the discount factor at the delivery date.
                forward_contract_delta = discount_rate

                # Flatten the book with delta hedging in forward markets.
                # delta + hedge-units * hedge-delta = 0
                # hence: hedge-units = -delta / hedge-delta
                hedge_units = -delta / forward_contract_delta

                # Present value of cost of hedge.
                hedge_cost = hedge_units * discounted_simulated_price_value

                periods.append({
                    'market_name': market_name,
                    'delivery_date': delivery_date,
                    'delta': delta,
                    'perturbation_name': perturbation_name,
                    'hedge_units': hedge_units,
                    'price_simulated': simulated_price_value,
                    'price_discounted': discounted_simulated_price_value,
                    'hedge_cost': hedge_cost,
                })

        return Results(fair_value, periods)
Example #10
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 #11
0
    def get_periods(self, contract_valuation):
        assert isinstance(contract_valuation, ContractValuation)

        market_simulation = self.market_simulation_repo[contract_valuation.market_simulation_id]

        call_result_id = make_call_result_id(contract_valuation.id, contract_valuation.contract_specification_id)
        call_result = self.call_result_repo[call_result_id]

        fair_value = call_result.result_value

        perturbation_names = call_result.perturbed_values.keys()
        perturbation_names = [i for i in perturbation_names if not i.startswith('-')]
        perturbation_names = sorted(perturbation_names, key=lambda x: [int(i) for i in x.split('-')[1:]])

        periods = []
        for perturbation_name in perturbation_names:

            perturbed_value = call_result.perturbed_values[perturbation_name]
            if contract_valuation.is_double_sided_deltas:
                perturbed_value_negative = call_result.perturbed_values['-' + perturbation_name]
            else:
                perturbed_value_negative = None
            # Assumes format: NAME-YEAR-MONTH
            perturbed_name_split = perturbation_name.split('-')
            market_name = perturbed_name_split[0]

            if market_name == perturbation_name:
                simulated_price_id = make_simulated_price_id(market_simulation.id, market_name,
                                                             market_simulation.observation_date,
                                                             market_simulation.observation_date)

                simulated_price = self.simulated_price_repo[simulated_price_id]
                price = simulated_price.value
                if contract_valuation.is_double_sided_deltas:
                    dy = perturbed_value - perturbed_value_negative
                else:
                    dy = perturbed_value - fair_value

                dx = market_simulation.perturbation_factor * price
                if contract_valuation.is_double_sided_deltas:
                    dx *= 2

                delta = dy / dx

                hedge_units = - delta
                hedge_cost = hedge_units * price
                periods.append({
                    'market_name': market_name,
                    'delivery_date': None,
                    'delta': delta,
                    'perturbation_name': perturbation_name,
                    'hedge_units': hedge_units,
                    'price_simulated': price,
                    'price_discounted': price,
                    'hedge_cost': hedge_cost,
                    'cash': -hedge_cost,

                })

            elif len(perturbed_name_split) > 2:
                year = int(perturbed_name_split[1])
                month = int(perturbed_name_split[2])
                if len(perturbed_name_split) > 3:
                    day = int(perturbed_name_split[3])
                    delivery_date = datetime.date(year, month, day)
                    simulated_price_id = make_simulated_price_id(
                        market_simulation.id, market_name, delivery_date, delivery_date
                    )
                    simulated_price = self.simulated_price_repo[simulated_price_id]
                    simulated_price_value = simulated_price.value

                else:
                    delivery_date = datetime.date(year, month, 1)
                    sum_simulated_prices = 0
                    count_simulated_prices = 0
                    for i in range(1, 32):
                        try:
                            _delivery_date = datetime.date(year, month, i)
                        except ValueError:
                            continue
                        else:
                            simulated_price_id = make_simulated_price_id(
                                market_simulation.id, market_name, _delivery_date, _delivery_date
                            )
                            try:
                                simulated_price = self.simulated_price_repo[simulated_price_id]
                            except KeyError:
                                pass
                            else:
                                sum_simulated_prices += simulated_price.value
                                count_simulated_prices += 1
                    assert count_simulated_prices, "Can't find any simulated prices for {}-{}".format(year, month)
                    simulated_price_value = sum_simulated_prices / count_simulated_prices

                # Assume present time of perturbed values is observation date.
                if contract_valuation.is_double_sided_deltas:
                    dy = perturbed_value - perturbed_value_negative
                else:
                    dy = perturbed_value - fair_value

                discount_rate = discount(
                    value=1,
                    present_date=market_simulation.observation_date,
                    value_date=delivery_date,
                    interest_rate=market_simulation.interest_rate
                )

                discounted_simulated_price_value = simulated_price_value * discount_rate

                dx = market_simulation.perturbation_factor * simulated_price_value
                if contract_valuation.is_double_sided_deltas:
                    dx *= 2
                delta = dy / dx

                # The delta of a forward contract at the observation date
                # is the discount factor at the delivery date.
                forward_contract_delta = discount_rate

                # Flatten the book with delta hedging in forward markets.
                # delta + hedge-units * hedge-delta = 0
                # hence: hedge-units = -delta / hedge-delta
                hedge_units = -delta / forward_contract_delta

                # Present value of cost of hedge.
                hedge_cost = hedge_units * discounted_simulated_price_value

                periods.append({
                    'market_name': market_name,
                    'delivery_date': delivery_date,
                    'delta': delta,
                    'perturbation_name': perturbation_name,
                    'hedge_units': hedge_units,
                    'price_simulated': simulated_price_value,
                    'price_discounted': discounted_simulated_price_value,
                    'hedge_cost': hedge_cost,
                    'cash': -hedge_cost,
                })
        return periods
Example #12
0
 def __getitem__(self, dt):
     assert isinstance(dt, datetime.datetime)
     app = get_quantdsl_app()
     return app.simulated_price_repo[make_simulated_price_id(
         self.simulation_id, self.name, dt)]