OK, now I have it:
type DiscountingBondEngine{Y <: YieldTermStructure} <: PricingEngine{Y}
yts::Y
function call(::Type{DiscountingBondEngine})
new{YieldTermStructure}()
end
function call{Y}(::Type{DiscountingBondEngine}, yts::Y)
new{Y}(yts)
end
end
This let's you call something like this with no issues:
pricing_engine = DiscountingBondEngine()
Then you can set the term structure later.
Julia is awesome.
Thanks!
Chris
On Friday, January 1, 2016 at 5:24:13 PM UTC-5, Christopher Alexander wrote:
>
> OK, I've gotten by this by doing:
>
> *B{AbstractA}()*
>
> ... but it would be neat if I could just infer that type in the inner
> constructor.
>
>
> On Friday, January 1, 2016 at 5:06:33 PM UTC-5, Christopher Alexander
> wrote:
>>
>> Thanks! I'm having a bit of trouble with that setup when the type is
>> parameterized, as below:
>>
>>
>>
>>
>> *abstract AbstractAtype A <: AbstractA endtype B{T <: AbstractA} a::T
>> B() = new()end*
>>
>> I am getting this error:
>>
>> *ERROR: MethodError: `convert` has no method matching
>> convert(::Type{B{T<:AbstractA}})*
>>
>> *This may have arisen from a call to the constructor
>> B{T<:AbstractA}(...),*
>>
>> *since type constructors fall back to convert methods.*
>>
>> Closest candidates are:
>>
>> convert{T}(::Type{T}, *::T*)
>>
>> call{T}(::Type{T}, *::Any*)
>>
>> in call at essentials.jl:57
>>
>> Is that the proper way to set that up?
>>
>> Thanks!!
>>
>> Chris
>>
>> On Friday, January 1, 2016 at 4:45:12 PM UTC-5, Tim Holy wrote:
>>>
>>> If you make `ts` the last parameter, using an inner constructor you can
>>> leave
>>> that field undefined when you initially create the object, then fill it
>>> in later.
>>> You may need to sprinkle some `isdefined(b, :ts)` in various places in
>>> your
>>> code.
>>>
>>> Happy New Year!
>>> --Tim
>>>
>>> On Friday, January 01, 2016 11:01:02 AM Christopher Alexander wrote:
>>> > I'm actually having a slight problem with this implementation.
>>> Basically,
>>> > in using the parametric approach above, when I initially create an
>>> instance
>>> > of the Bond type with the NullTermStructure and then set its term
>>> structure
>>> > with the new TermStructure instance that I create (creating the
>>> circular
>>> > reference), I get a convert error. I'm assuming this is because the
>>> > initial instantiation of the Bond wants a TermStructure of type
>>> > NullTermStructure, so then when I try to re-set it with
>>> PiecewiseYieldCurve,
>>> > it complains. Is there any way to avoid setting it with the
>>> > NullTermStructure in the first place?
>>> >
>>> > Thanks!
>>> >
>>> > Chris
>>> >
>>> > On Friday, January 1, 2016 at 1:24:21 PM UTC-5, Christopher Alexander
>>> wrote:
>>> > > Thanks Tim, this is very helpful! Happy New Year!
>>> > >
>>> > > - Chris
>>> > >
>>> > > On Thursday, December 31, 2015 at 6:33:29 PM UTC-5, Tim Holy wrote:
>>> > >> See
>>> > >>
>>> http://docs.julialang.org/en/stable/manual/faq/#how-do-abstract-or-ambigu
>>> > >> ous-fields-in-types-interact-with-the-compiler and the section
>>> > >> afterwards. You'd be better off with
>>> > >>
>>> > >> type Bond{T<:TermStructure}
>>> > >>
>>> > >> rate::Float64
>>> > >> ts::T
>>> > >> mat_dat::Date
>>> > >>
>>> > >> end
>>> > >>
>>> > >> --Tim
>>> > >>
>>> > >> On Thursday, December 31, 2015 02:42:11 PM Christopher Alexander
>>> wrote:
>>> > >> > Hello all,
>>> > >> >
>>> > >> > I have a question about the usage of circular references in
>>> types. In
>>> > >>
>>> > >> a
>>> > >>
>>> > >> > project I am working on, I am running into several situations
>>> where
>>> > >>
>>> > >> this
>>> > >>
>>> > >> > type of design appears to be the best issue. For example, let's
>>> say I
>>> > >>
>>> > >> have
>>> > >>
>>> > >> > this (this is a massive simplification but illustrates my point):
>>> > >> >
>>> > >> > abstract TermStructure
>>> > >> >
>>> > >> >
>>> > >> > type Bond
>>> > >> > rate::Float64
>>> > >> > ts::TermStructure
>>> > >> > mat_date::Date
>>> > >> > end
>>> > >> >
>>> > >> >
>>> > >> > function Bond(rate::Float64, mat_date::Date)
>>> > >> >
>>> > >> > ts = NullTermStructure()
>>> > >> > return Bond(rate, ts, mat_date)
>>> > >> >
>>> > >> > end
>>> > >> >
>>> > >> >
>>> > >> > type NullTermStructure <: TermStructure end
>>> > >> >
>>> > >> >
>>> > >> > type PiecewiseYieldCurve <: TermStructure
>>> > >> > settlement::Date
>>> > >> > bonds::Vector{Bond}
>>> > >> > end
>>> > >> >
>>> > >> >
>>> > >> > function PiecewiseYieldCurve(settlement::Date, sched::Schedule,
>>> rate::
>>> > >> > Float64)
>>> > >> >
>>> > >> > bonds = Vector{Bond}(length(sched))
>>> > >> > for (i, d) in enumerate(sched)
>>> > >> >
>>> > >> > new_bond = Bond(rate, d)
>>> > >> > bonds[i] = new_bond
>>> > >> >
>>> > >> > end
>>> > >> >
>>> > >> > pyc = PiecewiseYieldCurve(settlement, bonds)
>>> > >> > for b in bonds
>>> > >> >
>>> > >> > b.ts = pyc
>>> > >> >
>>> > >> > end
>>> > >> >
>>> > >> > return pyc
>>> > >> >
>>> > >> > end
>>> > >> >
>>> > >> >
>>> > >> > Firstly, I guess, is this the best implementation? There are
>>> > >>
>>> > >> situations
>>> > >>
>>> > >> > where I need the bonds of the PiecewiseYieldCurve to be aware of
>>> the
>>> > >> > TermStructure to which they are connected. Secondly, do I take a
>>> > >> > performance hit from this? The PiecewiseYieldCurve instance will
>>> have
>>> > >> > parts of it updated as I run some of my pricer methods (not
>>> shown).
>>> > >> >
>>> > >> > Thanks!
>>> > >> >
>>> > >> > Chris
>>>
>>>