def test_cashflow_currency_conversion(self) -> None:
     model = _make_model()
     self.assertEqual(model.currencies, {"EUR", "USD"})
     c = When(At(model.dategrid[-1]), Stock("ABC") * One("EUR"))
     cf_eur = c.generate_cashflows(model.eval_date_index, model)
     self.assertRaises(AssertionError, lambda: model.in_currency(cf_eur, "GBP"))
     cf_usd = model.in_currency(cf_eur, "USD")
     self.assertEqual(cf_eur.cashflows.shape, cf_usd.cashflows.shape)
     self.assertEqual(cf_usd.currencies[0], "USD")
     cf_eur_conv = model.in_numeraire_currency(cf_usd)
     self.assertEqual(cf_eur_conv.currencies[0], "EUR")
     self.assertTrue(
         np.allclose(cf_eur.cashflows["value"], cf_eur_conv.cashflows["value"])
     )
     # test with deterministic spots
     numeraire = np.ones((1, model.dategrid.size), dtype=np.float_)
     ccyspot = np.arange(1, model.dategrid.size + 1, dtype=np.float_).reshape(
         numeraire.shape
     )
     model2 = Model(
         model.dategrid, {}, {("UND", "ACC"): ccyspot}, {}, numeraire, "UND"
     )
     self.assertEqual(model2.currencies, {"UND", "ACC"})
     for i, dt in enumerate(model2.dategrid):
         c = When(At(dt), One("UND"))
         cf_und = c.generate_cashflows(model2.eval_date_index, model2)
         cf_acc = model2.in_currency(cf_und, "ACC")
         self.assertEqual(cf_acc.cashflows["value"][0, 0], i + 1)
     for i, dt in enumerate(model2.dategrid):
         c = When(At(dt), One("ACC"))
         cf_acc = c.generate_cashflows(model2.eval_date_index, model2)
         cf_und = model2.in_numeraire_currency(cf_acc)
         self.assertEqual(cf_und.cashflows["value"][0, 0], 1 / (i + 1))
 def test_rates(self) -> None:
     model = _make_model()
     dategrid = model.dategrid.flatten()
     yearfraction = (dategrid[-1] - dategrid[-3]).astype(np.float64) / 365
     c = When(
         At(model.dategrid[-1]),
         FixedAfter(At(dategrid[-3]), LinearRate("EUR", "3M"))
         * yearfraction
         * One("EUR"),
     )
     cf = model.generate_cashflows(c)
     self.assertEqual(cf.currencies.shape, (1,))
     self.assertEqual(cf.cashflows.shape, (model.nsim, 1))
     self.assertTrue((cf.cashflows["date"] == model.dategrid[-1]).all())
     self.assertEqual(cf.currencies[0], "EUR")
 def test_fixed_after(self) -> None:
     model = _make_model()
     fixed1 = FixedAfter(AlternatingBool(), Stock("ABC"))
     fixed1sim = fixed1.simulate(model.eval_date_index, model)
     altsim = AlternatingBool().simulate(model.eval_date_index, model)
     self.assertTrue(
         np.allclose(fixed1sim[altsim[:, 0], 0], fixed1sim[altsim[:, 0], -1])
     )
     self.assertFalse(
         np.isclose(fixed1sim[~altsim[:, 0], 0], fixed1sim[~altsim[:, 0], -1]).any()
     )
     fixed2 = FixedAfter(At(model.dategrid[-2, 0]), Stock("ABC"))
     fixed2sim = fixed2.simulate(model.eval_date_index, model)
     self.assertTrue(np.allclose(fixed2sim[:, -2], fixed2sim[:, -1]))
     self.assertFalse(np.isclose(fixed2sim[:, -3], fixed2sim[:, -1]).any())
     # ensure fixing condition is checked after first_observation_idx
     always = Stock("ABC") > 0
     fixed3 = FixedAfter(always, Stock("ABC"))
     fixed3sim1 = fixed3.simulate(model.eval_date_index, model)
     self.assertTrue(
         np.allclose(
             fixed3sim1,
             np.repeat(model.simulated_stocks["ABC"][:, :1], model.ndates, axis=1),
         )  # all columns equal to first one as immediately fixed
     )
     fixed3sim2 = fixed3.simulate(
         DateIndex(model.eval_date_index.index + model.ndates - 1), model
     )
     self.assertTrue(
         np.allclose(fixed3sim2, Stock("ABC").simulate(model.eval_date_index, model))
     )
 def test_contract_creation(self) -> None:
     And(
         Or(
             Cond(AlternatingBool(), Zero(), One("USD")),
             When(At(np.datetime64("2030-07-14")), One("EUR")),
         ),
         Give(Scale(KonstFloat(1.23), One("USD"))),
     )
     KonstFloat(1.23)
     KonstFloat(123)
 def test_stock(self) -> None:
     model = _make_model()
     c = When(At(model.dategrid[-1]), Stock("ABC") * One("EUR"))
     cf = model.generate_cashflows(c)
     self.assertEqual(cf.currencies.shape, (1,))
     self.assertEqual(cf.cashflows.shape, (model.nsim, 1))
     self.assertTrue(
         (cf.cashflows["value"][:, 0] == model.simulated_stocks["ABC"][:, -1]).all()
     )
     self.assertTrue((cf.cashflows["date"] == model.dategrid[-1]).all())
     self.assertEqual(cf.currencies[0], "EUR")
 def test_when_cashflow_generation(self) -> None:
     model = _make_model()
     cf = model.generate_cashflows(When(At(model.dategrid[0]), One("EUR")))
     self.assertEqual(cf.currencies.shape, (1,))
     self.assertEqual(cf.currencies[0], "EUR")
     self.assertEqual(cf.cashflows.shape, (model.nsim, 1))
     self.assertTrue((cf.cashflows["value"] == 1).all())
     self.assertTrue((cf.cashflows["date"] == model.dategrid[0]).all())
     cf1 = model.generate_cashflows(When(At(model.dategrid[1]), One("EUR")))
     self.assertEqual(cf1.currencies.shape, (1,))
     self.assertTrue(cf1.currencies[0], "EUR")
     self.assertEqual(cf1.cashflows.shape, (model.nsim, 1))
     self.assertTrue((cf1.cashflows["value"] == 1).all())
     self.assertTrue((cf1.cashflows["date"] == model.dategrid[1]).all())
     cf2 = model.generate_cashflows(When(AlternatingBool(), One("EUR")))
     self.assertEqual(cf2.currencies.shape, (1,))
     self.assertTrue(cf2.currencies[0], "EUR")
     self.assertEqual(cf2.cashflows.shape, (model.nsim, 1))
     self.assertTrue(
         (cf2.cashflows["value"][np.arange(0, model.nsim, 2), :] == 0).all()
     )
     self.assertTrue(
         (cf2.cashflows["value"][np.arange(1, model.nsim, 2), :] == 1).all()
     )
 def test_date_index(self) -> None:
     model = _make_model()
     at0 = At(model.dategrid[0])
     idx0 = model.eval_date_index.next_after(
         at0.simulate(model.eval_date_index, model)
     )
     self.assertTrue((idx0.index == 0).all())
     at1 = At(model.dategrid[1])
     idx1 = model.eval_date_index.next_after(
         at1.simulate(model.eval_date_index, model)
     )
     self.assertTrue((idx1.index == 1).all())
 def test_equity_black_scholes(self) -> None:
     dategrid = np.arange(
         np.datetime64("2020-01-01"),
         np.datetime64("2020-01-10"),
         dtype="datetime64[D]",
     )
     rnd = np.random.RandomState(seed=123)
     ndates = dategrid.size
     n = 100
     m = simulate_equity_black_scholes_model(
         "ABC", "EUR", 123, dategrid, 0.2, 0.2, n, rnd, use_moment_matching=True
     )
     self.assertIn("ABC", m.simulated_stocks)
     self.assertEqual(m.simulated_stocks["ABC"].shape, (n, ndates))
     self.assertEqual(m.numeraire.shape, (n, ndates))
     for t in dategrid:
         c = When(At(t), Stock("ABC") * One("EUR"))
         self.assertTrue(np.isclose(m.evaluate(c), 123))
 def test_or_cashflow_generation(self) -> None:
     model = _make_model()
     c2 = One("EUR") | When(At(model.dategrid[-1]), One("EUR"))
     self.assertRaises(NotImplementedError, lambda: model.generate_cashflows(c2))
     c3 = One("EUR") | 2 * One("EUR")
     cf = model.generate_cashflows(c3)
     self.assertEqual(cf.currencies.shape, (2,))
     self.assertEqual(cf.currencies[0], "EUR")
     self.assertEqual(cf.currencies[1], "EUR")
     self.assertEqual(cf.cashflows.shape, (model.nsim, 2))
     self.assertTrue((cf.cashflows["value"][:, 0] == 0).all())
     self.assertTrue((np.isnat(cf.cashflows["date"][:, 0])).all())
     self.assertTrue((cf.cashflows["value"][:, 1] == 2).all())
     self.assertTrue((cf.cashflows["date"][:, 1] == model.eval_date).all())
     c4 = One("EUR") | One("USD")
     cf4 = model.generate_cashflows(c4)
     self.assertEqual(cf4.currencies.shape, (2,))
     self.assertEqual(cf4.currencies[0], "EUR")
     self.assertEqual(cf4.currencies[1], "USD")
 def test_discounting(self) -> None:
     dategrid = np.arange(
         np.datetime64("2020-01-01"),
         np.datetime64("2020-06-01"),
         30,
         dtype="datetime64[D]",
     )
     rnd = np.random.RandomState(seed=123)
     n = 100
     rate = 0.03
     model = simulate_equity_black_scholes_model(
         "ABC", "USD", 123, dategrid, 0.2, rate, n, rnd, use_moment_matching=True
     )
     for t in dategrid:
         c = When(At(t), One("USD"))
         cf = c.generate_cashflows(model.eval_date_index, model)
         npv = model.discount(cf)[:, 0].mean()
         self.assertEqual(model.evaluate(c), npv)
         self.assertEqual(model.evaluate(cf), npv)
         dt = (t - dategrid[0]).astype(np.float64) / 365
         self.assertTrue(np.isclose(npv, np.exp(-rate * dt)))
     model.evaluate(When(Stock("ABC") > 130, One("USD")))
 def test_contract_str(self) -> None:
     c = (
         Cond((Stock("ABC") > 28) & ~(Stock("DEF") > 28), Zero(), One("USD"))
         | When(At(np.datetime64("2030-07-14")), One("EUR"))
     ) + (
         Until(FX("EUR", "USD") < 1.0, -(1.23 * One("USD")))
         + Anytime(
             (Stock("DEF") >= 50) | (Stock("DEF") < 20),
             Stock("ABC") * One("EUR"),
         )
     )
     expected = (
         "And(Or(Cond((Stock(ABC) > 28) & (~(Stock(DEF) > 28)), Zero, One(USD)), "
         "When(2030-07-14, One(EUR))), And(Until(~(FX(EUR/USD) >= 1.0), "
         "Give(Scale(1.23, One(USD)))), Anytime((Stock(DEF) >= 50) "
         "| (~(Stock(DEF) >= 20)), Scale(Stock(ABC), One(EUR)))))"
     )
     self.assertEqual(str(c), expected)
     c2 = (Stock("ABC") ** 2 / (Stock("DEF") - 1.7) + 42) * One("EUR")
     self.assertEqual(
         str(c2),
         "Scale((((Stock(ABC)) ** (2)) / ((Stock(DEF)) + (-1.7))) + (42), One(EUR))",
     )
 def test_boolean_obs_at(self) -> None:
     model = _make_model()
     at0 = At(model.dategrid[0])
     at0sim = at0.simulate(model.eval_date_index, model)
     self.assertEqual(at0sim.dtype, np.bool_)
     self.assertEqual(at0sim.shape, model.shape)
     self.assertTrue(at0sim[:, 0].all())
     self.assertFalse(at0sim[:, 1].any())
     at1 = At(model.dategrid[1])
     at1sim = at1.simulate(model.eval_date_index, model)
     self.assertEqual(at1sim.dtype, np.bool_)
     self.assertEqual(at1sim.shape, model.shape)
     self.assertFalse(at1sim[:, 0].any())
     self.assertTrue(at1sim[:, 1].all())
     alt = AlternatingBool()
     altsim = alt.simulate(model.eval_date_index, model)
     self.assertFalse(altsim[np.arange(0, model.nsim, 2), :].any())
     self.assertTrue(altsim[np.arange(1, model.nsim, 2), :].all())
 def resolve(self) -> Contract:
     return When(At(self.maturity), self.notional * One("EUR"))
 def test_evaluation(self) -> None:
     model = _make_model()
     c = When(At(model.dategrid[-1]), One("EUR"))
     npv = model.evaluate(c)
     self.assertEqual(npv, 1)