JuliaFinance / Roadmap

13 stars 1 forks source link

Some thoughts... #4

Open EricForgy opened 5 years ago

EricForgy commented 5 years ago

I'd like to try to get some momentum going πŸ™

Currencies

I think we need to think about Currencies.jl a little bit.

I recently split out CurrenciesBase.jl from Currencies.jl, but I still think CurrenciesBase does too much πŸ€”

The issue is that you can speak about USD without talking about 1.0USD. For example, if I want to specify the currency of a bank account, I'd like to have a type Currency available for that.

Now, if we want to talk about a specific quantity in a certain currency, this is like a position in a stock, e.g. 400 shares of Apple stock. We have 400 units of USD.

Countries

Similar to currency, we need a way to specify countries. Like currencies, there are ISO standards for country codes, etc.

I think we need standard identifiers/codes for both countries and currencies.

Holdings

As mentioned above, I think we should differentiate a currency or financial instrument from a position in that currency or financial instrument.

For example, if AAPL is an instance of a financial instrument, i.e. Apple stock, then we should distinguish AAPL from 400 shares of AAPL. In one case, we're talking about a financial instrument itself. In the other, we're talking about ownership or a position in that instrument.

Similarly, if USD is an instance of a currency, then we should distinguish USD from a position of 400 units of USD.

One way I've thought of to deal with this is to consider currencies and financial instruments as units so we can write things like

julia>1AAPL+2AAPL
3AAPL

More recently, I've been thinking about this more from an accounting perspective so we can have ledger accounts. Maybe the two ways of thinking about it are compatible. I'm still just starting to think about it now.

Ledgers

I'm working on a ledger package now along similar lines to @TotalVerb's Accounting.jl.

If we can construct a general ledger with chart of accounts, then that could be the foundation to everything from personal finance to corporate financial reporting. I'll try to get something preliminary out soon and welcome more brains helping to think about this stuff.

I know accounting feels boring, but the more I get into modeling it, the more I like it. After all, even sexy things like derivatives trading boils down to P&L at the end of the day, so having a good foundation on which to build more quant stuff makes sense to me.

Interest Rate Models

Interest rate modeling is cool. I'm sure most Julia quants will be drawn to interest rate derivatives etc. However, I am interested in yield curve forecasts for balance sheet projections and capital management.

Interest rate models used for derivative pricing are notoriously poor at forecasting yield curves. Similarly, econometric models use to forecast yield curves are generally poor for derivatives pricing because they tend to not be arbitrage free.

I'm greedy and want both 😊 There are some models I have in mind to implement that should straddle both derivatives pricing and yield curve forecasting. Still early stages for me though and most of the work is handwritten notes so far πŸ˜…

Regulatory Reporting

Financial services are regulated and every regulator has a different approach to solvency and capital adequacy. I think there are some good opportunities to implement regulatory capital models in Julia.

Quant Stuff

Then, of course, I think most people looking to Julia for use in finance will be interested in quant work 😊

That is fun. I admit, but I also think it would be good to have quant packages built on some common foundational packages around currencies, countries, accounting treatments, etc.

Everyone can and should at some point build a Black-Scholes solver, but wouldn't it be nicer if your models plugged directly into an accounting system? πŸ˜…

Other Stuff?

The above kind of outlines my personal priorities. I'm happy to join forces with others with different priories and would love to hear about them. Maybe I am a dreamer, but I'm hoping there can be some core financial functionality on which various other domains can grow upon rather than having every new package define its own currency module πŸ˜… AND... having accounting treatment thought about from the beginning.

felipenoris commented 5 years ago

I've been working on a very similar idea to Miletus.jl, based on the same article, and it's turning into a bigger system, built upon a stack of packages that I have contributed over the years (Mongoc.jl, Oracle.jl, BusinessDays.jl, InterestRates.jl, XLSX.jl, JSONWebTokens.jl, Vol.jl), and also non-Julia packages (math-server-docker, hyper-reverse-proxy, bdays).

In order to keep things modular and reusable in financial systems, you must put big effort on keeping database data and business logic separated. For instance, should a ExchangeRateTable be part of a Currency module? It's of course modeling database data that is bound to a particular instant in time.

Concepts in a Financial Toolbox

The way I see concepts organized:

Currency

Provides:

Daycount

BusinessDays

Rates

See InterestRates.jl.

Term Structures

See InterestRates.jl.

Contract Primitives

Provides a language for defining a financial contract based on the article. This is the overlap with the work in JuliaComputing's Miletus package. But JuliaComputing should release Miletus code under a liberal license in order to help us contribute these ideas, given the big overlap.

Read this and this first.

On the use of Fixed Decimals and/or truncation rules for Contracts

Portfolio and Positions (holdings)

At this point, you can see that a Cash defined in the Currencies section is not a holding and is almost useless. It just provides some syntax sugar given its algebra functionality.

Volatility Models

Volatility estimation techniques. See Vol.jl.

Market Risk Models

Regulatory Reports

Portfolio Optimization

Asset-Liability Management

Algo Trading

Conclusion

As you can see, this is biased to a market risk framework, but may be useful to guide future development in this group. It is the result of years of thinking, so I hope it helps. :D

EricForgy commented 5 years ago

Hey! Good to see you here @felipenoris! πŸ˜ƒ

(And just before I posted this I noticed you already started moving some of your packages to JuliaFinance. That is awesome! Thanks πŸ’ͺπŸŽ‰πŸ˜ƒ)

Thank you for your thoughts πŸ™Œ

It is encouraging to see so much alignment in the way we think about things 😊

Some comments below...

Currency

Provides:

  • a Currency, identified by a Symbol.
  • a Cash as a number bounded to a currency, using Miletus terminology.
  • the algebra around Cash values.
  • a probably abstract type for a provider of Exchange Rates. This will be implemented by the user, probably linked to a database.
  • an exchange method to support the implementation of the exch primitive defined in the article, given a provider of Exchange Rates.

I agree we need all this, but one of my points above is we need to think about where to put it.

For me, binding a number to a currency is no different than binding a number to any other financial instrument. It is a "holding" and is probably better in a Portfolio or Positions (or even an Accounting) package. So I kind of hope we can make Currencies.jl very boring with almost nothing more than the ISO standard and then layer in additional functionality in higher-level packages that apply to all financial instruments including cash.

Have you looked into any financial instrument classifications? To me, that has always been a huge challenge, especially with large multinational financial institutions. I like the CFI classification standard https://www.anna-web.org/standards/cfi-iso-10962/. Spot cash is listed as a financial instrument. It makes sense since cash has a bid-ask spread.

So I think something like Cash as a number bound to a currency belongs in a higher-level package that applies to all financial instruments. What do you think? πŸ€”

I have similar thoughts about an ExchangeRate provider. I don't think exchange rates belong in a minimal Currencies package because exchange rates are market driven with a bid-ask spread, etc. So I think for exchange rates, we probably also need a higher-level package, something like Markets. Markets would be like a living provider that you can query quotes for all financial instruments, e.g. cash, stocks, bonds, etc.

I see a Market as providing all the market data required to price fiancial instruments specific to that market, e.g. yield curves, stock quotes, implied vol, etc. Then we have another specific set of inter-market factors or MarketLinkages that relate to multiple markets, e.g. quotes for fx rates, fx forwards, cross-currency swaps, etc.

A Market could be a layer between Julia and Bloomberg, Reuters, etc but could also be based purely on simulated or mock data.

Daycount

  • implements all day count conventions
  • provides daycount and yearfraction methods

See DayCounts.jl 😊

BusinessDays

  • implements local calendars for day counting routines

I was going to provide the link to your own BusinessDays.jl, but see you already moved it to JuliaFinance

https://github.com/JuliaFinance/BusinessDays.jl

That is awesome. Thank you! πŸ™ŒπŸ˜ƒπŸŽ‰

Rates

  • implements compounding types (exponential, linear, continuous)
  • provides erf (effective rate), discountfactor, and aux methods to convert a rate to and from an erf or discountfactor

See InterestRates.jl.

Term Structures

  • provides an abstract type for interest rate curve
  • implements all common interpolation models for a given set of observed zero-rates.
  • implements all common term structure models for a given set of model parameters

See InterestRates.jl.

πŸ’―

Contract Primitives

Provides a language for defining a financial contract based on the article. This is the overlap with the work in JuliaComputing's Miletus package. But JuliaComputing should release Miletus code under a liberal license in order to help us contribute these ideas, given the big overlap.

It looks like you've put a lot more thought into this than I have πŸ˜…

I am a little hesitate to put too much weight on Miletus and the articles it is based on. Although I have no doubt it is probably appealing from an academic perspective, I don't think it has been adopted by the markets. Maybe it is fine, but I'm not ready to jump into that commitment with both feet yet πŸ˜… I could be convinced otherwise though and interested to hear more of your thoughts on the subject.

A lot of what what you described in this section can be broken down into smaller packages. Let's try to map out what those smaller packages might look like πŸ˜ŠπŸ™

Portfolio and Positions (holdings)

  • A Position is a quantity of a given Contract. Positive (long) or negative (short).
  • a Portfolio has a set of Positions for every point in time, and can have metadata like its strategy, accounting category and so on.
  • a Trade is a transaction that alters the composition of a Portfolio. It is defined by a transaction price, a contract (portfolio?), the quantity of contracts and it targets a Portfolio.
  • From a Portfolio's historical record, one could get reports on P&L (Profit and Loss), and related metrics.

This all sounds good πŸ‘ The only thing I wonder about is if we should move some of this functionality into an Accounting package or create tight linkages to an Accounting package πŸ€” I am interested in real-time balance sheet montoring so when a trade is made, I'd like to see this pass directly to a journal entry and reflected on the general ledger in real time. I know this is not normal practice, but it is something I hope to implement nonetheless πŸ˜…πŸ™

At this point, you can see that a Cash defined in the Currencies section is not a holding and is almost useless. It just provides some syntax sugar given its algebra functionality.

I see we have slight difference of opinion on this πŸ˜… A mentor once told me that the most complicated financial instrument on the market is cash (and I've grown to agree with him) πŸ˜… Although it seems trivial, there is a rabbit hole that can go pretty deep especially with global multicurrency portfolios. I think it makes sense to keep cash on par with other portfolio holdings.

Regulatory Reports

  • this is a thing where I work. we even put up a sketch package that is being privately developed further: see BaselBrazil.jl. But, as being a top-of-the-stack package and very specific to brazilian regulation, it's not useful for many people.
  • I can imagine that the standard model from the paper of the Basel Committee can benefit from this kind of work.

That is awesome. Yeah. Would be awesome to build these reports in Julia. Not only for banking, but insurance as well 😊 We could probably even get support from a few regulators.

Well, welcome to JuliaFinance @felipenoris! It is great to see you here and I'm excited about what we can do here πŸš€πŸ˜Š

felipenoris commented 5 years ago

Nice! Just a note on what I meant on my comments about Cash: if defined on Currencies, the only benefit we get from it is it's algebra (doing things like 1.4USD returns a Cash instance for currency USD of 1.4 units).

Later on the stack of packages, the Contract Primitives package defines a Financial Contract for this as a Scale(1.4, Unit(SpotCurrency(USD))). Which is equivalent to cash, but now it is a contract. You can also define an Adapter to convert one to another.

So, what I meant is that when you define it in the currencies package, you're just providing a syntax sugar, and it is not a holding yet. And this gives my opinion on the answer for your initial question about how to define holdings.

EricForgy commented 5 years ago

It is late where you are πŸ’€πŸ˜ƒ (PS: I'm on Slack. Might be easier to discuss there 😊)

tk3369 commented 5 years ago

This is very exciting! On and off, I have been thinking about building a Julia library that blows quantlib away. I have fixed income asset management background so I can possibly contribute in various aspects of pricing, analytics, etc.

EricForgy commented 5 years ago

That's awesome @tk3369. Welcome! πŸ˜ƒ

EricForgy commented 5 years ago

I just created two new repos:

These are embarassingly boring and could probably be implemented much better than what I did. Feedback / PRs welcome πŸ˜…πŸ™

I found a good data source for countries here so included more data than I was initially planning to include. So a Country instance contains the following fields:

struct Country
    name::String
    code::Int
    currency::Currencies.Currency
    capital::String
    continent::String
    developed::Bool
    region::String
    subregion::String
end
simonbyrne commented 5 years ago

One way I've thought of to deal with this is to consider currencies and financial instruments as units so we can write things like

julia>1AAPL+2AAPL
3AAPL

This was actually my plan for the next iteration of Miletus: my idea was that you specify everything in terms of "basic assets" (e.g. currencies, stocks, commodities), and then the "price" is simply the relative value of one asset compared to another. The nice thing is that a forex derivative is the same as a stock market derivative.

EricForgy commented 5 years ago

This was actually my plan for the next iteration of Miletus: my idea was that you specify everything in terms of "basic assets" (e.g. currencies, stocks, commodities), and then the "price" is simply the relative value of one asset compared to another.

Cash makes a good numeraire 😊 But keep in mind that each market, e.g. HK, SG, US, UK, will have it's own local numeraire.

Any more thoughts on when / if parts of Miletus can be open sourced? 😊

@felipenoris and I have been discussing it here and elsewhere and agree that contracts are of fundamental importance to JuliaFinance. We are both working on other priorities right now though, so there is time to think about it, but at some point, we'll need contracts to make further progress πŸ™πŸ˜Š

tk3369 commented 5 years ago

Both currency and country are common reference data for financial instruments. For space efficiency reasons, I would prefer that we define an enum type (USD/EUR/etc and US/EU/etc) for general reference. Then, a dictionary can be used to look up detailed information about that currency or country.

From a user perspective:

stock = Stock("AAPL", USD, US)
code(stock.country)  # "US"
code2(stock.country) # "US"
code3(stock.country) # "USA"
name(stock.country) # "United States"
country"US" # parser returns US
EricForgy commented 5 years ago

Both currency and country are common reference data for financial instruments. For space efficiency reasons, I would prefer that we define an enum type (USD/EUR/etc and US/EU/etc) for general reference. Then, a dictionary can be used to look up detailed information about that currency or country.

From a user perspective:

stock = Stock("AAPL", USD, US)
code(stock.country)  # "US"
code2(stock.country) # "US"
code3(stock.country) # "USA"
name(stock.country) # "United States"
country"US" # parser returns US

Hi @tk3369 πŸ‘‹

I've seen this handled various ways and happy to discuss to find the best way forward 😊

I did it this way because I didn't think space would be an issue, but I can see your point.

It could be done with @enum or what about just singleton types?

For example,

abstract type Currency end
struct USD <: Currency end

I did think about enums, but they felt a little clumsy to me, but maybe I am exposing ignorance πŸ˜…

Singleton types would allow us to dispatch on countries and currencies. Not sure of the pros and cons though.

Open to ideas 😊

simonbyrne commented 5 years ago

Two other points re currencies

  1. While decimal fixed point is nice for basic accounting purposes, for more complex calculations (e.g. option pricing) floats are more useful.
  2. It would be nice to integrate with Unitful.jl (though it's not immediately clear how one would do it).
tk3369 commented 5 years ago

Hi Eric, I'm unsure if there's any reason to dispatch on specific currency/country. I'm good with either enum or symbol -- leaning more on enum since it's typed.

Regarding:

  • A Position is a quantity of a given Contract. Positive (long) or negative (short).
  • a Portfolio has a set of Positions for every point in time, and can have metadata like its strategy, accounting category and so on.
  • a Trade is a transaction that alters the composition of a Portfolio. It is defined by a transaction price, a contract (portfolio?), the quantity of contracts and it targets a Portfolio.
  • From a Portfolio's historical record, one could get reports on P&L (Profit and Loss), and related metrics.

A Position may consist of many Lot's. A Lot is the portion of position that came from a specific trade. For example, if you buy AAPL 3 times at 3 different prices, then each lot would represent the quantity from each trade. You can imagine that each lot is the same as a position object with additional attributes - id, trade date, broker, acquisition price, etc.

Now that's where things become hairy. When you have multiple lots in a portfolio, a sell trade against that position may relieve the lots based upon a specific accounting treatment - e.g. FIFO, LIFO, average, etc. A portfolio accounting system would take it seriously and make sure that the right lots are relieved. However, a general-purpose portfolio management system would ignore that effect and just look at the portfolio at the position level (after all, the remaining number of shares is the same). P/L calculation requires proper lot accounting. Typically a portfolio would have a default lot relief convention but the investor has the ability to select specific lots (e.g. I can do that on E*Trade).

A Trade represents the transaction of a single financial instrument. Nowadays, it's easy to execute multi-leg trades. For example, a butterfly trade involves 3 option trade legs. Let's say we call this bundle MultiLegTrade. When designing Trade and MultiLegTrade, we should take into account of specific fields that are common. In the above example, you would not have 3 different trade dates for each leg since the trades are actually executed at the same time (typically).

Fixed income instruments are more complex. One of the issues is that bonds may have embedded options. So a Bond may contain one or more Option and therefore it's more like a composite type. FX is another instrument that's "out of ordinary" as it requires an exchange of two Cash instruments.

Generally, a portfolio's holdings can be constructed from a trade log. It would be convenient to have a "replay" function that takes a portfolio from point A in time, and bring it to a different state at point B by executing a series of trades.

tk3369 commented 5 years ago

Perhaps we should add another type for Analytic's. An analytic can be viewed as a time series for a financial instrument at a given date/time. Some analytics are daily (e.g. closing price) and some may be continuous during trading hours (e.g. current price or option delta). The analytic may be linked to a specific market condition (e.g. yield curve, interpolation method, etc.)

I would imagine having a framework where one can add various kinds of calculators for these analytics. Each calculator should cover a number of financial instruments e.g. I would not calculate duration for stocks, nor would I calculate P/E for bonds.

Having said that, it would be nice to define a set of traits for each financial instruments so these functions can operate on them only if the traits are satisfied. (Speaking of which, I would be very happy when traits becomes officially supported in Julia.)

EricForgy commented 5 years ago

Hi Eric, I'm unsure if there's any reason to dispatch on specific currency/country. I'm good with either enum or symbol -- leaning more on enum since it's typed.

Regarding:

  • A Position is a quantity of a given Contract. Positive (long) or negative (short).
  • a Portfolio has a set of Positions for every point in time, and can have metadata like its strategy, accounting category and so on.
  • a Trade is a transaction that alters the composition of a Portfolio. It is defined by a transaction price, a contract (portfolio?), the quantity of contracts and it targets a Portfolio.
  • From a Portfolio's historical record, one could get reports on P&L (Profit and Loss), and related metrics.

A Position may consist of many Lot's. A Lot is the portion of position that came from a specific trade. For example, if you buy AAPL 3 times at 3 different prices, then each lot would represent the quantity from each trade. You can imagine that each lot is the same as a position object with additional attributes - id, trade date, broker, acquisition price, etc.

Now that's where things become hairy. When you have multiple lots in a portfolio, a sell trade against that position may relieve the lots based upon a specific accounting treatment - e.g. FIFO, LIFO, average, etc. A portfolio accounting system would take it seriously and make sure that the right lots are relieved. However, a general-purpose portfolio management system would ignore that effect and just look at the portfolio at the position level (after all, the remaining number of shares is the same). P/L calculation requires proper lot accounting. Typically a portfolio would have a default lot relief convention but the investor has the ability to select specific lots (e.g. I can do that on E*Trade).

A Trade represents the transaction of a single financial instrument. Nowadays, it's easy to execute multi-leg trades. For example, a butterfly trade involves 3 option trade legs. Let's say we call this bundle MultiLegTrade. When designing Trade and MultiLegTrade, we should take into account of specific fields that are common. In the above example, you would not have 3 different trade dates for each leg since the trades are actually executed at the same time (typically).

Fixed income instruments are more complex. One of the issues is that bonds may have embedded options. So a Bond may contain one or more Option and therefore it's more like a composite type. FX is another instrument that's "out of ordinary" as it requires an exchange of two Cash instruments.

Generally, a portfolio's holdings can be constructed from a trade log. It would be convenient to have a "replay" function that takes a portfolio from point A in time, and bring it to a different state at point B by executing a series of trades.

This is great insight @tk3369 πŸ‘ We're definitely on the same page.

I think we agree that some early thinking on how to handle accounting of trades (and lots) makes sense and that is kind of what I'm doing now, but I got distracted looking into AbstractTrees.jl. I think it could be useful for us, but maybe needs some enhancements / modifications.

I know @felipenoris 's priority is yield curve stuff (Rates and TermStructures). All of this eventually links back to Contracts 😊

EricForgy commented 5 years ago

Hey @felipenoris , @simonbyrne πŸ‘‹

@tk3369 made this comment about Country and Currency

Hi Eric, I'm unsure if there's any reason to dispatch on specific currency/country. I'm good with either enum or symbol -- leaning more on enum since it's typed.

Do you have any thoughts?

EricForgy commented 5 years ago

Any thoughts on renaming Currencies.jl to CurrencyBaskets.jl or something?

This would leave Currencies.jl to be similar to Countries.jl which are likely going to be just enums with some table lookups.

@TotalVerb ?

felipenoris commented 5 years ago

Regarding dispatch on currency, that is useful for dispatch on parametric types down the road. We could dispatch on values also, like Array{Int64, 2} dispatches on the value 2, but having a type for it just makes it an easier syntax, which is desirable, but not required.

For instance, the algebra around monetary values uses dispatch to guarante that 1USD + 2EUR cannot be summed (related to the comment on Unitful.jl).

Exchange rates could be modeled using dispatch on currency types like so:

function exch(p::AbstractExchangeRateProvider, from::C, to::C) :: Float64 where {C<:Currencies.Currency}
    # same currency
    return 1.0
end

function exch(p::AbstractExchangeRateProvider, from::C1, to::C2) :: Float64 where {C1<:Currencies.Currency, C2<:Currencies.Currency}

    if !haskey(p, from) # ex.: BRL -> USD
        @assert haskey(p, to)
        @assert cashcurrency(p[to]) == from
        return 1.0 / cashvalue(p[to])

    elseif cashcurrency(p[from]) == to # ex.: USD -> BRL
        return cashvalue(p[from])

    else
        @assert haskey(p, to)
        @assert cashcurrency(p[from]) == cashcurrency(p[to]) # same functional currency
        return cashvalue(p[from]) / cashvalue(p[to])
    end
end

Dispatch on countries is something less required, in my mind. One could also dispatch on values for countries anyway.

felipenoris commented 5 years ago

Regarding @simonbyrne comment on Fixed Decimals, that's something I've been thinking about in the last few weeks.

What I think about it for now is this:

EricForgy commented 5 years ago

Thanks for the input @felipenoris πŸ™Œ

That is a good point about dispatching on currencies. It looks like we could either

  1. Define Currency as an enum and dispatch on values or
  2. Define Currency as an abstract type and each currency would be a concrete singleton subtype.

Between the two, I am slightly inclined to go with singleton types for currencies πŸ€”

Now, I also think it could come in handy if we could dispatch on countries, e.g. different countries have different laws, different tax regimes, different regulatory reporting requirements, etc. On regulatory reporting, sometimes you might want to look at what a Malaysian company would look like under Hong Kong capital adequacy. Maybe the Malaysian company has a Hong Kong parent or someone in Hong Kong is considering an acquisition.

On a more technical note, I've been looking at traits lately and it feels like I'm looking at the future. It is starting to shift the way I think about coding in Julia. I think having concrete singleton types for both currency and country could come in handy if we start implementing traits.

Then we could do things like:

subregion(::US) = NorthAmerica()
subregion(::HK) = EastAsia()
subregion(::GB) = NorthernEurope()

subregionanalysis(x) = subregionanalysis(x,subregion(x))
subregionanalysis(x,::NorthAmerica) = ...
subregionanalysis(x,::EastAsia) = ...
subregionanalysis(x,::NorthEurope) = ...

At first, the advantage of traits over usual subtyping of abstract types wasn't very obvious to me, but if you think about extensibility of interfaces, it starts to make sense.

See the discussion starting here: https://github.com/JuliaLang/julia/issues/2345#issuecomment-54601332

From timholy:

Maybe it will be easier to appreciate this if I say it this way: this proposal is a traits-based alternative to multiple inheritance, something people have been wanting in Julia for a long time. In some ways it's nicer, because I don't have to create specialized types that live at the intersection of parents, I can just declare that, based on their parameters, some objects have all the properties of two different types of objects.

felipenoris commented 5 years ago

I like the pragmatic approach where you don't do things until you need them.

If that's something important for you, go ahead.

If there's no clear vision, don't do it until you need it.

I'm sure Currency would be just an enum if someone didn't get yet to the implementation on algebra around cash values.

But this is somewhat subjective. So if you're the guy coding Countries, go for what you think is the best design. If down the road it is not, an issue will be opened on that repo.

EricForgy commented 5 years ago

Sounds good. Let me put it this way...

Singleton subtypes are simple to implement, efficient, and appear future proof to me. I don't see a downside to making currencies and countries (and regions and subregions etc) singleton subtypes.

Before I go ahead and implement singleton subtypes, can you guys think of a downside?

Edit: Some links with some interesting related discussions:

https://discourse.julialang.org/t/singleton-types-vs-instances-as-type-parameters/2802

https://discourse.julialang.org/t/naming-of-singleton-types-and-their-instance/8399

http://www.stochasticlifestyle.com/type-dispatch-design-post-object-oriented-programming-julia

felipenoris commented 5 years ago

Downsides that come to my mind are minor stuff:

EricForgy commented 5 years ago
  • name clash. That's why I never use export or use in any of my packages. (I think this also happens with enums, anyway)

Yeah. Agree. I'd never export all those names πŸ˜…

  • you possibly can't redefine them during a Julia session, if you plan to change the list of countried from time to time (I may be wrong in this one).

This is actually where traits could come in handy.

Let's say, you wanted to run a simulation or create your own country. In your package, you could define

struct MyCountry <: Country end
subregion(::MyCountry) = EastAsia()

Now, subregionanalysis(MyCountry()) will "just work" because it ultimately gets dispatched on EastAsia since

subregionanalysis(x) = subregionanalysis(x,subregion(x))

This is a decent illustration of how traits help with extensibility 😊

You could do the same with value types though, but I think we agree that feels a little clumsier.

felipenoris commented 5 years ago

Which means that, whatever solution is given, enum or type, we could add an abstract type. This will integrate nicely with future traits, I guess.

tk3369 commented 5 years ago

Very good discussions here. I appreciate the thoughtfulness of the comments and the desire to do it right from the beginning.

I can't think of a reason why singleton subtypes wouldn't work. It may be good to just do it and battle test with real use cases e.g. defining a type for cash instruments, a currency forward contract, etc. and any possible issues would surface as part of the exercise.

EricForgy commented 5 years ago

Sounds good. I will give it a shot, but I'm still spinning my wheels a bit with my ledger stuff and trying to incorporate AbstractTrees πŸ˜…

I should just push out something still under construction for feedback πŸ€”

felipenoris commented 5 years ago

Just added a few more insights on the use of Fixed Decimals in my first post (the 2nd post of this thread).

alecloudenback commented 5 years ago

Hi everyone, one thought that I had as I read some of the discussions going on....

Regarding rates, ie interest rates, when applied in a valuation context, could be more generalized to be a type of Decrement that can be stacked along with other decrements. This would be useful in an actuarial context where you have multiple types of decrements when valuing a contract (deaths, lapses, incidence, etc). In a sense, in an actuarial present value there's nothing particular special about interest rates - and all the different types of decrements can be stochastic.

Looking at InterestRates.jl, it seems like that's more focused on just mechanics of yield curves and such, not on valuation so I'm not exactly sure where to point my feedback to yet.

EricForgy commented 5 years ago

Hi @alecloudenback πŸ‘‹

Funny you mention that, I was thinking the exact same thing this morning (Manila time which is a few hours ago). In the same context too! πŸ˜ƒ

Lots of things can create a term structure of spreads:

From an actuarial perspective, as you note, you have things like

You can also have things like

In fact, when I was at Countrywide structuring MBS, we were using mortality models for prepayment risk because the mechanics are similar 😊

I had in mind a general package for TermStructures which seems similar to Decrements.

I love this thinking! πŸ˜ƒ

bfcondon commented 5 years ago

Hey, I am new to Julia but know Python pretty well. My background is in structured finance, high yield bonds and leveraged loans mostly. I am interested in contributing as this gets going. One area that has been mentioned is around a Ledger for tracking cashflows or account balances or as @tk3369 said an Analytic to describe cash flows. I believe these are related and useful primitives.

ScottPJones commented 5 years ago

Regarding @simonbyrne comment on Fixed Decimals, that's something I've been thinking about in the last few weeks.

@felipenoris I was wondering about what you felt about using IEEE Decimal Floats (i.e. as in DecFP.jl) instead of relying on Float64? I haven't retested in a while, but Dec128 got better performance (and much better memory usage) than using BigFloat, if you ran into issues with rounding / precision.

alecloudenback commented 5 years ago

@EricForgy brought this up over at https://github.com/JuliaFinance/Roadmap/issues/8 but I thought I would just clarify by what I mean by abstracting interest rates to be a form of more generic "decrements". I think that the design decision needs to depend partly on how contracts/assets/cashflows are designed because when I think about how decrements are applied, it's in valuing those things.

Here's a simple example though:

function value(notional, decrements,cfs)
    sum(notional * (prod(decrements,dims=2) .* cfs))
end

#life insurance
interest_rate = [0.05 for x=1:10]
discount_vector = cumprod((1 ./ (1 .+ interest_rate)))
mortality = [0.01 * x for x=0:9]
survival = cumprod(1 .- mortality,dims=1)

value(100,hcat(discount_vector, survival),q) # 31.678928945567804

#bond
interest_rate = [0.05 for x=1:10]
discount_vector = cumprod(1 .- interest_rate,dims=1)
bond_payments = [x== 10 ? 1.1 : 0.1 for x=1:10]

value(100,discount_vector,bond_payments) # 136.11367546854586

This example separates out the "things that discount the future value" from the "thing that you are valuing" but doesn't really care what the discounting functions are.

You could go even further and consider combining the cfs with the decrements and consider both a representation of the pieces of each decrement that you are pulling into your value, e.g.:

I want 95% (interest decrement) of the 99% of the survivor's expected 2% of the contract, times the notional value of the contract

and change the definition of value to:

function value2(notional, decrements)
   sum(notional * prod(decrements,dims=2))    
end

and hcat the cfs with the decrements.

I think the latter might be going too far and it would be practical to separate the cashflows from the decrements.

And like @EricForgy mention, swap out mortality for defaults and you have the workings of a credit model, so this is pretty broad based in application.

alecloudenback commented 5 years ago

One additional thought is that decrements should have the ability to interact with observables (in the SPJ sense) as things like default rates, lapse rates, or prepayment rates might vary by exogenous factors.