Implementing trait behavior

Now that we can tell which types are liquid and which are not, we can define methods that take objects with those traits. First, let's do something really simple:

# The thing is tradable if it is liquid
tradable(x::T) where {T} = tradable(LiquidityStyle(T), x)
tradable(::IsLiquid, x) = true
tradable(::IsIlliquid, x) = false

In Julia, types are first-class citizens. The tradable(x::T) where {T} signature captures the type of argument as T. Since we have already defined the LiquidityStyle function, we can derive whether the passed argument exhibits the IsLiquid or IsIlliquid trait. So, the first tradable method simply takes the return value of LiquidityStyle(T) and passes it as the first argument for the other two tradable methods. This simple example demonstrates the dispatch effect.

Now, let's look at a more interesting function that exploits the same trait. Since liquid assets are easily tradable in the market, we should be able to discover their market price quickly as well. For stocks, we may call a pricing service from the stock exchange. For cash, the market price is just the currency amount. Let's see how this is coded:

# The thing has a market price if it is liquid
marketprice(x::T) where {T} = marketprice(LiquidityStyle(T), x)
marketprice(::IsLiquid, x) = error("Please implement pricing function for ", typeof(x))
marketprice(::IsIlliquid, x) = error("Price for illiquid asset $x is not available.")

The code's structure is the same as the tradable function. One method is used to determine the trait, while the other two methods implement different behaviors for the liquid and illiquid instruments. Here, both marketprice functions just raise an exception by calling the error function. Of course, that's not what we really want. What we should really have is a specific pricing function for the Stock and Money types. Okay; let's do just that:

# Sample pricing functions for Money and Stock
marketprice(x::Money) = x.amount
marketprice(x::Stock) = rand(200:250)

Here, the marketprice method for the Money type just returns the amount. This is quite a simplification since, in practice, we may calculate the amount in the local currency (for example, US Dollars) from the currency and amount. As for Stock, we just return a random number for the purpose of testing. In reality, we would have attached this function to a stock pricing service.

For illustration purposes, we have developed the following test functions:

function trait_test_cash()
cash = Money("USD", 100.00)
@show tradable(cash)
@show marketprice(cash)
end

function trait_test_stock()
aapl = Stock("AAPL", "Apple, Inc.")
@show tradable(aapl)
@show marketprice(aapl)
end

function trait_test_residence()
try
home = Residence("Los Angeles")
@show tradable(home) # returns false
@show marketprice(home) # exception is raised
catch ex
println(ex)
end
return true
end

function trait_test_bond()
try
bill = TreasuryBill("123456789")
@show tradable(bill)
@show marketprice(bill) # exception is raised
catch ex
println(ex)
end
return true
end

Here's the result from the Julia REPL:

Perfect! The tradable function has correctly identified that cash, stock, and bond are liquid and that residence is illiquid. For cash and stocks, the marketprice function was able to return a value, as expected. Because residence is not liquid, an error was raised. Finally, while treasury bills are liquid, an error was raised because the marketprice function has not been defined for the instrument.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.2.184