packages feed

netrium-0.6.0: examples/WeatherContingent.contract

contract =
    weatherContingentMonthLeg
        monthlyPremium buyersAggregateLimitAmount sellersAggregateLimitAmount
        notionalAmount dailyDeductable weatherIndex gasIndexStrikeLevel
        previousAggregatePayment
        dailySch calcDate
  where
    monthlyPremium              = 10
    buyersAggregateLimitAmount  = m 14.5
    sellersAggregateLimitAmount = m 11
    notionalAmount              = k 330
    dailyDeductable             = k 137.5
    gasIndexStrikeLevel         = 80
    previousAggregatePayment    = konst 0
    weatherIndex                = [ 4.03, 4.02, 4.01 ]
    dailySch                    = [ date 2011 1 d | d <- [1..3] ]
    calcDate                    = date 2011 2 5

m = (*1000000)
k = (*1000)

-----------------------------------------------------------------------

weatherContingentMonthLeg
  monthlyPremium buyersAggregateLimitAmount sellersAggregateLimitAmount
  notionalAmount dailyDeductable
  weatherIndexStrikeSchedule gasIndexStrikeLevel
  previousAggregatePayment
  dailySch calcDate =

    foldr daily monthEnd (zip dailySch weatherIndexStrikeSchedule) (konst 0)

  where
    daily (day, weatherIndexStrikeLevel) next dailyPaymentSum =
      when (at day) $
        letin "dailyPaymentSum"
          (dailyPaymentSum
           %+ dailyPayment notionalAmount dailyDeductable
                           weatherIndexStrikeLevel gasIndexStrikeLevel)
          (\dailyPaymentSum' -> next dailyPaymentSum')

    monthEnd dailyPaymentSum =
      when (at calcDate) $
        financial paymentDue gbp cash

      where
        -- Aggregate Payment Amount:
        -- For a given Calculation Date, if the sum of the Daily Payment Amounts in
        -- the period from the Effective Date to the last Day of the month prior to
        -- such Calculation Date is:
        --   (i) positive, then the Aggregate Payment Amount will equal the minimum
        --       of; (a) the sum of the Daily Payment Amounts, and (b) the Buyer's
        --       Aggregate Limit Amount, or
        -- 
        --   (ii) negative, then the Aggregate Payment Amount will equal the maximum
        --        of (a) the sum of the Daily Payment Amounts, and (b) the Seller's
        --        Aggregate Limit Amount multiplied by negative one.
        --
        aggregatePayment =
          ifthen (dailyPaymentSum %>= konst 0)
                 (min dailyPaymentSum (konst buyersAggregateLimitAmount))
                 (max dailyPaymentSum (konst sellersAggregateLimitAmount))

        -- Payment Amount:
        -- On each Payment Date the Payment Amount will equal the Aggregate Payment
        -- Amount for the respective Calculation Date less the Aggregate Payment
        -- Amount for the previous Calculation Date apart from the first Payment
        -- Date where the Payment Amount will be the Aggregate Payment Amount.
        paymentAmount = aggregatePayment %- previousAggregatePayment

        paymentDue =
          -- If the Payment Amount is:
          -- (i)   positive, and Payment Amount less the Monthly Premium is positive
          --       then Seller shall pay Buyer a sum equal to Payment Amount less
          --       the Monthly Premium in GBP, or
          ifthen (paymentAmount %> konst 0
                  %&& (paymentAmount %- konst monthlyPremium) %>= konst 0)
                 (negate (paymentAmount %- konst monthlyPremium)) $

          -- (ii)  positive, and Payment Amount less the Monthly Premium is negative
          --       then Buyer shall pay Seller a sum equal to Monthly Premium less
          --       the Payment Amount.
          ifthen (paymentAmount %> konst 0
                  %&& (paymentAmount %- konst monthlyPremium) %< konst 0)
                 (konst monthlyPremium %- paymentAmount) $

          -- (iii) negative, then Buyer shall pay Seller an amount equal to the
          --       absolute value of the Payment Amount in GBP plus the Monthly
          --       Premium, or
          ifthen (paymentAmount %< konst 0)
                 (abs (paymentAmount %+ konst monthlyPremium))

          -- (iv)  zero, the Buyer shall pay Seller the Monthly Premium.
          (konst monthlyPremium)


    dailyPayment notionalAmount dailyDeductable
                 weatherIndexStrikeLevel gasIndexStrikeLevel =

        -- Daily Payment Amount:
        -- Where Daily Accrual Amount is positive the Daily Payment Amount due to
        -- the Buyer shall be calculated as follows:
        ifthen (dailyAccrual %> konst 0)
          -- Daily Payment Amount =
          --   Max ((Daily Accrual Amount - Daily Deductible),0)
          (max (dailyAccrual %- konst dailyDeductable) (konst 0))

          -- Where Daily Accrual Amount is negative the Daily Payment Amount due to
          -- the Seller shall be calculated as follows:
          --
          -- Daily Payment Amount = Daily Accrual Amount
          (negate dailyAccrual)

      where
        -- Daily Accrual Amount:
        dailyAccrual =
        -- If:
        -- Natural Gas Settlement Price < Natural Gas Index Strike Level
          ifthen
            (gas_settlement_price  %< konst gasIndexStrikeLevel)
        -- Daily Accrual Amount shall be:
        --
        -- Relevant Notional Amount
        --   * [Weather Index - Weather Index Strike Level]
        --   * [Natural Gas Index Strike Level - Natural Gas Settlement Price]
            (konst notionalAmount
              %* (weather_metro_grp_CWV %- konst weatherIndexStrikeLevel)
              %* (konst gasIndexStrikeLevel %- gas_settlement_price ))

        -- Where Relevant Notional Amount relates to the Notional Amount applicable
        -- to the month in which the relevant Daily Accrual Amount falls.
        --
        -- A positive result is a Daily Accrual Amount in favour of the Buyer and
        -- a negative result is a Daily Accrual Amount in favour of the Seller.

        -- If:
        -- Natural Gas Settlement Price > or = Natural Gas Index Strike Level
        -- then, Daily Accrual Amount shall be zero.
            (konst 0)