539 lines
16 KiB
XML
539 lines
16 KiB
XML
<?xml version="1.0"?>
|
|
<!--
|
|
Copyright (C) 2014-2023 Ryan Specialty, LLC.
|
|
|
|
This file is part of tame-core.
|
|
|
|
tame-core is free software: you can redistribute it and/or modify it
|
|
under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation, either version 3 of the
|
|
License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
-->
|
|
<package xmlns="http://www.lovullo.com/rater"
|
|
xmlns:c="http://www.lovullo.com/calc"
|
|
xmlns:t="http://www.lovullo.com/rater/apply-template"
|
|
core="true"
|
|
title="Insurance Abstractions">
|
|
|
|
<import package="base" />
|
|
<import package="assert" export="true" />
|
|
<import package="convention" export="true" />
|
|
<import package="map" export="true" />
|
|
<import package="numeric/round" export="true" />
|
|
<import package="vector/cmatch" export="true" />
|
|
|
|
|
|
These are primitive abstractions for insurance that will be
|
|
improved upon over time.
|
|
|
|
Some notable TODOs:
|
|
|
|
\begin{enumerate}
|
|
\item Support scalar results; and
|
|
\item Rounding direction (currently only nearest).
|
|
\end{enumerate}
|
|
|
|
\todo{Template to abstract these {\tt rate-each} generation
|
|
templates.}
|
|
|
|
<param name="assert_ignore_premium_zero" type="boolean"
|
|
desc="Ignore assertion failures for $0 premiums" />
|
|
|
|
<param name="assert_ignore_premium_negative" type="boolean"
|
|
desc="Ignore assertion failures for negative premiums" />
|
|
|
|
|
|
<template name="_premium_"
|
|
desc="A premium dollar amount">
|
|
<param name="@values@" desc="Body" />
|
|
<param name="@class@" desc="Predicate" />
|
|
|
|
<param name="@no@" desc="Negated predicate">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@sym@" desc="TeX symbol">
|
|
<text></text>
|
|
</param>
|
|
<param name="@gensym@" desc="Generator TeX symbol">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@yields@" desc="Yield (optional)">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@generates@" desc="Generates (optional)">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@index@" desc="Index (optional)">
|
|
<text></text>
|
|
</param>
|
|
|
|
<!-- at least one of generates or yields is required -->
|
|
<if name="@yields@" eq="">
|
|
<if name="@generates@" eq="">
|
|
<error>must provide at least one of @generates or @yields</error>
|
|
</if>
|
|
</if>
|
|
|
|
<unless name="@generates@" eq="">
|
|
<t:naming-convention name="@generates@" prefix="prem" />
|
|
</unless>
|
|
|
|
<unless name="@yields@" eq="">
|
|
<t:naming-convention name="@yields@" prefix="prem" />
|
|
</unless>
|
|
|
|
<!-- required since various companies have various bizzare
|
|
rounding rules that tend to be a source of bugs; make the
|
|
developer think about it -->
|
|
<param name="@round@" desc="Rounding method" />
|
|
|
|
<!-- not yet used, but it will at least serve as code
|
|
documentation for the time being -->
|
|
<param name="@desc@" desc="Premium description" />
|
|
<unless name="@desc@">
|
|
<unless name="@generates@" eq="">
|
|
<error>
|
|
a description (@desc@) is required for
|
|
`<param-value name="@generates@" />'
|
|
</error>
|
|
</unless>
|
|
<if name="@generates@" eq="">
|
|
<error>
|
|
a description (@desc@) is required for
|
|
`<param-value name="@yields@" />'
|
|
</error>
|
|
</if>
|
|
</unless>
|
|
|
|
<param name="@allow-zero@" desc="Allow value of zero (default false)">
|
|
<text>false</text>
|
|
</param>
|
|
|
|
<param name="@allow-negative@" desc="Allow negative value (default false)">
|
|
<text>false</text>
|
|
</param>
|
|
|
|
|
|
<rate-each class="@class@" no="@no@" yields="@yields@"
|
|
generates="@generates@" index="@index@"
|
|
sym="@sym@" gensym="@gensym@">
|
|
<!-- TODO: we now have reason for a more concise conditional
|
|
syntax -->
|
|
<if name="@round@" eq="dollar">
|
|
<t:round>
|
|
<param-copy name="@values@" />
|
|
</t:round>
|
|
</if>
|
|
<unless name="@round@" eq="dollar">
|
|
<if name="@round@" eq="cent">
|
|
<c:apply name="round_cents">
|
|
<c:arg name="round_cents_val">
|
|
<param-copy name="@values@" />
|
|
</c:arg>
|
|
</c:apply>
|
|
</if>
|
|
|
|
<unless name="@round@" eq="cent">
|
|
<if name="@round@" eq="up">
|
|
<c:ceil>
|
|
<param-copy name="@values@" />
|
|
</c:ceil>
|
|
</if>
|
|
|
|
<unless name="@round@" eq="up">
|
|
<if name="@round@" eq="down">
|
|
<c:floor>
|
|
<param-copy name="@values@" />
|
|
</c:floor>
|
|
</if>
|
|
|
|
<unless name="@round@" eq="down">
|
|
<!-- no rounding -->
|
|
<param-copy name="@values@" />
|
|
</unless>
|
|
</unless>
|
|
</unless>
|
|
</unless>
|
|
</rate-each>
|
|
|
|
|
|
<!-- assertion for non-zero -->
|
|
<unless name="@allow-zero@" eq="true">
|
|
<unless name="@generates@" eq="">
|
|
<t:assert failure="{@desc@} ({@generates@}) must not yield a value
|
|
of 0 for any index">
|
|
<any>
|
|
<match on="assert_ignore_premium_zero" />
|
|
<t:match-ne on="@generates@" value="ZERO" />
|
|
</any>
|
|
</t:assert>
|
|
</unless>
|
|
|
|
<unless name="@yields@" eq="">
|
|
<t:assert failure="{@desc@} ({@yields@}) must not yield a value of 0">
|
|
<any>
|
|
<match on="assert_ignore_premium_zero" />
|
|
<t:match-ne on="@yields@" value="ZERO" />
|
|
</any>
|
|
</t:assert>
|
|
</unless>
|
|
</unless>
|
|
|
|
<!-- assertion for non-negative -->
|
|
<unless name="@allow-negative@" eq="true">
|
|
<unless name="@generates@" eq="">
|
|
<t:assert failure="{@desc@} ({@generates@}) must not yield a negative
|
|
value for any index">
|
|
<any>
|
|
<match on="assert_ignore_premium_negative" />
|
|
<t:match-gte on="@generates@" value="ZERO" />
|
|
</any>
|
|
</t:assert>
|
|
</unless>
|
|
|
|
<unless name="@yields@" eq="">
|
|
<t:assert failure="{@desc@} ({@yields@}) must not yield a negative
|
|
value">
|
|
<any>
|
|
<match on="assert_ignore_premium_negative" />
|
|
<t:match-gte on="@yields@" value="ZERO" />
|
|
</any>
|
|
</t:assert>
|
|
</unless>
|
|
</unless>
|
|
</template>
|
|
|
|
|
|
\ref{_factor_} defines a calculation that results in a factor
|
|
which will later be used in a product.
|
|
There are special considerations for these types of values---%
|
|
generally, they should not have a value of~$0$ if some sort of calculation
|
|
condition or lookup is not met,
|
|
as that would have the effect of wiping out premium.\footnote{
|
|
Note that every generator index can be non-zero but still sum up
|
|
to a zero yield,
|
|
which would trigger this error.}
|
|
If zero is desired,
|
|
\tt{@allow-zero@} must be set to \tt{true} to explicitly permit it.
|
|
|
|
<template name="_factor_"
|
|
desc="Factor to multiply against (must be non-zero by default)">
|
|
<param name="@values@" desc="Body" />
|
|
|
|
<param name="@class@" desc="Predicate">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@generates@" desc="Generator name">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@index@" desc="Generator index">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@no@" desc="Negated predicate">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@sym@" desc="TeX symbol">
|
|
<text></text>
|
|
</param>
|
|
<param name="@gensym@" desc="Generator TeX symbol">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@yields@" desc="Yield (optional)">
|
|
<text></text>
|
|
</param>
|
|
|
|
<!-- at least one of generates or yields is required -->
|
|
<if name="@yields@" eq="">
|
|
<if name="@generates@" eq="">
|
|
<error>must provide at least one of @generates or @yields</error>
|
|
</if>
|
|
</if>
|
|
|
|
<!-- not yet used, but it will at least serve as code
|
|
documentation for the time being -->
|
|
<param name="@desc@" desc="Factor description" />
|
|
<unless name="@desc@">
|
|
<unless name="@generates@" eq="">
|
|
<error>
|
|
a description (@desc@) is required for
|
|
`<param-value name="@generates@" />'
|
|
</error>
|
|
</unless>
|
|
<if name="@generates@" eq="">
|
|
<error>
|
|
a description (@desc@) is required for
|
|
`<param-value name="@yields@" />'
|
|
</error>
|
|
</if>
|
|
</unless>
|
|
|
|
<!-- normally we want factors to default to 1, otherwise they could wipe
|
|
out premium -->
|
|
<param name="@allow-zero@" desc="Allow value of zero (default false; see
|
|
also @default@)">
|
|
<text>false</text>
|
|
</param>
|
|
|
|
<!-- default is _only_ used when a factor is 0, so it makes no sense to
|
|
set a default to #0 -->
|
|
<param name="@default@" desc="Default value if 0 (optional)" />
|
|
<if name="@default@" eq="#0">
|
|
<error>
|
|
a value of #0 for @default@ is not meaningful;
|
|
use @allow-zero@ instead.
|
|
</error>
|
|
</if>
|
|
|
|
<!-- negative values might be indicitive of a failure to provide a floor
|
|
on certain factors when summing (for example) -->
|
|
<param name="@allow-negative@" desc="Allow negative value (default false)">
|
|
<text>false</text>
|
|
</param>
|
|
|
|
<param name="@_prefix@" desc="Factor type (drives naming convention)">
|
|
<text>factor</text>
|
|
</param>
|
|
|
|
<unless name="@generates@" eq="">
|
|
<t:naming-convention name="@generates@" prefix="@_prefix@" />
|
|
</unless>
|
|
|
|
<unless name="@yields@" eq="">
|
|
<t:naming-convention name="@yields@" prefix="@_prefix@" />
|
|
</unless>
|
|
|
|
|
|
<!-- factor calculation -->
|
|
<rate-each class="@class@" no="@no@" yields="@yields@" sym="@sym@"
|
|
generates="@generates@" index="@index@" gensym="@gensym@">
|
|
<!-- use a default if provided if the factor expression yields 0 -->
|
|
<if name="@default@">
|
|
<c:let>
|
|
<c:values>
|
|
<c:value name="factor" type="float"
|
|
desc="Factor result before default">
|
|
<param-copy name="@values@" />
|
|
</c:value>
|
|
</c:values>
|
|
|
|
<t:map-set name="factor">
|
|
<t:map from="ZERO" value="@default@" />
|
|
<t:map-else value="factor" />
|
|
</t:map-set>
|
|
</c:let>
|
|
</if>
|
|
|
|
<!-- avoid let generation if no default was provided -->
|
|
<unless name="@default@">
|
|
<param-copy name="@values@" />
|
|
</unless>
|
|
</rate-each>
|
|
|
|
|
|
<!-- assertion for non-zero -->
|
|
<unless name="@allow-zero@" eq="true">
|
|
<!-- assertions are useless if a static default was provided, since we
|
|
know that zero can then never be yielded-->
|
|
<unless name="@default@" prefix="#">
|
|
<unless name="@generates@" eq="">
|
|
<t:assert failure="{@generates@} must not yield a value of 0 for
|
|
any index">
|
|
<t:match-ne on="@generates@" value="ZERO" />
|
|
</t:assert>
|
|
</unless>
|
|
|
|
<unless name="@yields@" eq="">
|
|
<t:assert failure="{@yields@} must not yield a value of 0">
|
|
<t:match-ne on="@yields@" value="ZERO" />
|
|
</t:assert>
|
|
</unless>
|
|
</unless>
|
|
</unless>
|
|
|
|
<!-- assertion for non-negative -->
|
|
<unless name="@allow-negative@" eq="true">
|
|
<unless name="@generates@" eq="">
|
|
<t:assert failure="{@generates@} must not yield a negative value
|
|
for any index">
|
|
<t:match-gte on="@generates@" value="ZERO" />
|
|
</t:assert>
|
|
</unless>
|
|
|
|
<unless name="@yields@" eq="">
|
|
<t:assert failure="{@yields@} must not yield a negative value">
|
|
<t:match-gte on="@yields@" value="ZERO" />
|
|
</t:assert>
|
|
</unless>
|
|
</unless>
|
|
</template>
|
|
|
|
|
|
The \ref{_credit_} and \ref{_debit_} templates define factors that are
|
|
intended to introduce, respectively, credits and surcharges.
|
|
Each name defined using these templates must be prefixed with ``credit''
|
|
and ``debit'' respectively.
|
|
Credits must never exceed a value of~$1$,
|
|
as they would then be treated as if they were surcharges.
|
|
Similarly, debits must never have a value less than~$1$.
|
|
Both must have values greater than~$0$.
|
|
|
|
If a value can be either a credit or a debit,
|
|
it is sometimes called an ``adjustment''.
|
|
In reality it is just another factor,
|
|
so just use \ref{_factor_} in such a~case.
|
|
|
|
<template name="_credit_"
|
|
desc="Credit to be used as a factor">
|
|
<param name="@values@" desc="Credit calculation" />
|
|
|
|
<param name="@class@" desc="Predicate">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@generates@" desc="Generator name">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@index@" desc="Generator index">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@no@" desc="Negated predicate">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@sym@" desc="TeX symbol">
|
|
<text></text>
|
|
</param>
|
|
<param name="@gensym@" desc="Generator TeX symbol">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@yields@" desc="Yield (optional)">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@default@" desc="Default value if 0 (optional)">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@desc@" desc="Factor description">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@allow-zero@" desc="Allow value of zero (default false)">
|
|
<text></text>
|
|
</param>
|
|
|
|
|
|
<t:factor _prefix="credit"
|
|
class="@class@" no="@no@" yields="@yields@" sym="@sym@"
|
|
generates="@generates@" index="@index@" gensym="@gensym@"
|
|
allow-zero="@allow-zero@"
|
|
default="@default@"
|
|
desc="@desc@">
|
|
<param-copy name="@values@" />
|
|
</t:factor>
|
|
|
|
<unless name="@generates@" eq="">
|
|
<t:assert failure="{@generates@} is a credit but one or more
|
|
of its values are greater than 1">
|
|
<t:match-lte on="@generates@" value="#1" />
|
|
</t:assert>
|
|
</unless>
|
|
|
|
<unless name="@yields@" eq="">
|
|
<t:assert failure="{@yields@} is a credit but its value is
|
|
greater than 1">
|
|
<t:match-lte on="@yields@" value="#1" />
|
|
</t:assert>
|
|
</unless>
|
|
</template>
|
|
|
|
|
|
<template name="_debit_"
|
|
desc="Debit to be used as a factor">
|
|
<param name="@values@" desc="Credit calculation" />
|
|
|
|
<param name="@class@" desc="Predicate">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@generates@" desc="Generator name">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@index@" desc="Generator index">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@no@" desc="Negated predicate">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@sym@" desc="TeX symbol">
|
|
<text></text>
|
|
</param>
|
|
<param name="@gensym@" desc="Generator TeX symbol">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@yields@" desc="Yield (optional)">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@default@" desc="Default value if 0 (optional)">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@desc@" desc="Factor description">
|
|
<text></text>
|
|
</param>
|
|
|
|
<param name="@allow-zero@" desc="Allow value of zero (default false)">
|
|
<text></text>
|
|
</param>
|
|
|
|
|
|
<t:factor _prefix="debit"
|
|
class="@class@" no="@no@" yields="@yields@" sym="@sym@"
|
|
generates="@generates@" index="@index@" gensym="@gensym@"
|
|
allow-zero="@allow-zero@"
|
|
default="@default@"
|
|
desc="@desc@">
|
|
<param-copy name="@values@" />
|
|
</t:factor>
|
|
|
|
<unless name="@generates@" eq="">
|
|
<t:assert failure="{@generates@} is a debit but one or more
|
|
of its values are less than 1">
|
|
<t:match-gte on="@generates@" value="#1" />
|
|
</t:assert>
|
|
</unless>
|
|
|
|
<unless name="@yields@" eq="">
|
|
<t:assert failure="{@yields@} is a credit but its value is
|
|
less than 1">
|
|
<t:match-gte on="@yields@" value="#1" />
|
|
</t:assert>
|
|
</unless>
|
|
</template>
|
|
</package>
|