Quantlib; how to use PiecewiseFlatForward - quantlib

I am using the function PiecewiseFlatForward to build a curve and I am using it by setting settlementDate as an "absolute" starting date, like PiecewiseFlatForward(settlementDate, swapHelpers, Actual360()), so that the curve should be unaffected by a resetting of the Settings.instance().evaluationDate. If I change Settings.instance().evaluationDate to a date in the past with respect to the original settlementDate, the reference date of the curve stays the same, but I get an error when trying to retrieve the forward rates (unlike when using the ForwardCurve function). Here the code, where after resetting the evaluation to a past date the same forwardRate function does not work (RuntimeError: 1st iteration: failed at 1st alive instrument, pillar March 16th, 2020, maturity March 16th, 2020, reference date November 27th, 2019: 2nd leg: negative time (-0.2) given):
calendar = TARGET()
todaysDate = Date(25, November, 2019)
Settings.instance().evaluationDate = todaysDate
settlementDate = Date(27, November, 2019)
calendar = TARGET()
swaps = {
(6,Months): 0.028067,
(12,Months): 0.030768,
(18,Months): 0.029352,
(24,Months): 0.028648,
(30,Months): 0.028532,
(36,Months): 0.028480,
(42,Months): 0.028420,
(48,Months): 0.028394,
(54,Months): 0.028382,
(60,Months): 0.028387}
fixedLegFrequency = Semiannual
fixedLegDayCounter = Thirty360()
fixedLegAdjustment = Unadjusted
swapHelpers = [ SwapRateHelper(QuoteHandle(SimpleQuote(swaps[(n,unit)])),
Period(n,unit), calendar,
fixedLegFrequency, fixedLegAdjustment,
fixedLegDayCounter, USDLibor(Period(6,Months)))
for n, unit in swaps.keys() ]
depoSwapCurve = PiecewiseFlatForward(settlementDate, swapHelpers, Actual360())
dates = [ spot+Period(i*6,Months) for i in range(0, len(swaps)) ]
rates = [ depoSwapCurve.forwardRate(d, USDLibor(Period(6,Months)).maturityDate(d), Actual360(), Simple).rate()
for d in dates ]
print rates
Settings.instance().evaluationDate = Date(12, September, 2019)
rates2 = [ depoSwapCurve.forwardRate(d, USDLibor(Period(6,Months)).maturityDate(d), Actual360(), Simple).rate()
for d in dates ]
print rates2
Is there a way to use the .forwardRate function without having to care about the evaluation date when the function used to build the curve is the PiecewiseFlatForward?

Are you sure there's nothing missing in the code you posted?
After correcting for the error NameError: name 'spot' is not defined (because spot is not defined in your code) with:
spot = calendar.advance(todaysDate, 2, Days)
it seems to work fine...

Related

Trouble using utcoffset with Chart.js

I'm trying to use Chart.js with a datetime x axis, and I need to adjust all my values by subtracting 5 hours. Here's some of my code:
var timeFormat = 'MM/DD HH:mm';
time: {
format: timeFormat,
tooltipFormat: 'll',
parser: function(utcMoment) {
return moment(utcMoment).utcOffset(5, true);
}
},
Without the parser function, my values are normal (10:00, January 10, 2021), but with the parser function, for some reason my values are set back all the way to 2001. Yes two-thousand-and-one.(10:00, January 10, 2001) Note that the time is not actually changed (So two errors: 1.time not adjusted when it should be. 2:years adjusted when it shouldn't be). Why could this be?
I will assume that the reason you want to roll it back by 5 hours is because of a timezone difference. If that's the case, you should use moment-timezone instead of moment.
With that said, subtracting 5 hours from the current date is actually simpler than what you're doing.
Before feeding a date into moment, you need to convert it to the js Date object like so: new Date('2021-01-10 00:00:00'). Since your parser function accepts the date in m/d H:M format, you would need to append the year to it first.
So here is how your code should look:
parser: function(utcMoment) {
const new_date = utcMoment.split(' ')[0] + '/' + (new Date().getFullYear()) + ' ' + utcMoment.split(' ')[1];
return moment(new Date(new_date)).subtract({hours: 5})
}

Calculating results pro rata over several months with PowerQuery

I am currently stuck on below issue:
I have two tables that I have to work with, one contains financial information for vessels and the other contains arrival and departure time for vessels. I get my data combining multiple excel sheets from different folders:
financialTable
voyageTimeTable
I have to calculate the result for above voyage, and apportion the result over June, July and August for both estimated and updated.
Time in June : 4 hours (20/06/2020 20:00 - 23:59) + 10 days (21/06/2020 00:00 - 30/06/2020 23:59) = 10.1666
Time in July : 31 full days
Time in August: 1 day + 14 hours (02/08/2020 00:00 - 14:00) = 1.5833
Total voyage duration = 10.1666 + 31 + 1.5833 = 42.7499
The result for the "updated" financialItem would be the following:
Result June : 100*(10.1666/42.7499) = 23.7816
Result July : 100*(31/42.7499) = 72.5148
Result August : 100*(1.5833/42.7499) = 3.7036
sum = 100
and then for "estimated" it would be twice of everything above.
This is the format I ideally would like to get:
prorataResultTable
I have to do this for multiple vessels, with multiple timespans and several voyage numbers.
Eagerly awaiting responses, if any. Many thanks in advance.
Brds,
Not sure if you're still looking for an answer, but code below gives me your expected output:
let
financialTable = Table.FromRows({{"A", 1, "profit/loss", 200, 100}}, type table [vesselName = text, vesselNumber = Int64.Type, financialItem = text, estimated = number, updated = number]),
voyageTimeTable = Table.FromRows({{"A", 1, #datetime(2020, 6, 20, 20, 0, 0), #datetime(2020, 8, 2, 14, 0, 0)}}, type table [vesselName = text, vesselNumber = Int64.Type, voyageStartDatetime = datetime, voyageEndDatetime = datetime]),
joined =
let
joined = Table.NestedJoin(financialTable, {"vesselName", "vesselNumber"}, voyageTimeTable, {"vesselName", "vesselNumber"}, "$toExpand", JoinKind.LeftOuter),
expanded = Table.ExpandTableColumn(joined, "$toExpand", {"voyageStartDatetime", "voyageEndDatetime"})
in expanded,
toExpand = Table.AddColumn(joined, "$toExpand", (currentRow as record) =>
let
voyageInclusiveStart = DateTime.From(currentRow[voyageStartDatetime]),
voyageExclusiveEnd = DateTime.From(currentRow[voyageEndDatetime]),
voyageDurationInDays = Duration.TotalDays(voyageExclusiveEnd - voyageInclusiveStart),
createRecordForPeriod = (someInclusiveStart as datetime) => [
inclusiveStart = someInclusiveStart,
exclusiveEnd = List.Min({
DateTime.From(Date.EndOfMonth(DateTime.Date(someInclusiveStart)) + #duration(1, 0, 0, 0)),
voyageExclusiveEnd
}),
durationInDays = Duration.TotalDays(exclusiveEnd - inclusiveStart),
prorataDuration = durationInDays / voyageDurationInDays,
estimated = prorataDuration * currentRow[estimated],
updated = prorataDuration * currentRow[updated],
month = Date.MonthName(DateTime.Date(inclusiveStart)),
year = Date.Year(inclusiveStart)
],
monthlyRecords = List.Generate(
() => createRecordForPeriod(voyageInclusiveStart),
each [inclusiveStart] < voyageExclusiveEnd,
each createRecordForPeriod([exclusiveEnd])
),
toTable = Table.FromRecords(monthlyRecords)
in toTable
),
expanded =
let
dropped = Table.RemoveColumns(toExpand, {"estimated", "updated", "voyageStartDatetime", "voyageEndDatetime"}),
expanded = Table.ExpandTableColumn(dropped, "$toExpand", {"month", "year", "estimated", "updated"})
in expanded
in
expanded
The code tries to:
join financialTable and voyageTimeTable, so that for each vesselName and vesselNumber combination, we know: estimated, updated, voyageStartDatetime and voyageEndDatetime.
generate a list of months for the period between voyageStartDatetime and voyageEndDatetime (which get expanded into new table rows)
for each month (in the list), do all the arithmetic you mention in your question
get rid of some columns (like the old estimated and updated columns)
I recommend testing it with different vesselNames and vesselNumbers from your dataset, just to see if the output is always correct (I think it should be).
You should be able to manually inspect the cells in the $toExpand column (of the toExpand step/expression) to see the nested rows before they get expanded.

How to build an inflation term structure in QuantLib?

This is what I've got, but I'm getting weird results. Can you spot an error?:
#Zero Coupon Inflation Indexed Swap Data
zciisData = [(ql.Date(18,4,2020), 1.9948999881744385),
(ql.Date(18,4,2021), 1.9567999839782715),
(ql.Date(18,4,2022), 1.9566999673843384),
(ql.Date(18,4,2023), 1.9639999866485596),
(ql.Date(18,4,2024), 2.017400026321411),
(ql.Date(18,4,2025), 2.0074000358581543),
(ql.Date(18,4,2026), 2.0297999382019043),
(ql.Date(18,4,2027), 2.05430006980896),
(ql.Date(18,4,2028), 2.0873000621795654),
(ql.Date(18,4,2029), 2.1166999340057373),
(ql.Date(18,4,2031), 2.152100086212158),
(ql.Date(18,4,2034), 2.18179988861084),
(ql.Date(18,4,2039), 2.190999984741211),
(ql.Date(18,4,2044), 2.2016000747680664),
(ql.Date(18,4,2049), 2.193000078201294)]
def build_inflation_term_structure(calendar, observationDate):
dayCounter = ql.ActualActual()
yTS = build_yield_curve()
lag = 3
fixing_date = calendar.advance(observationDate,-lag, ql.Months)
convention = ql.ModifiedFollowing
cpiTS = ql.RelinkableZeroInflationTermStructureHandle()
inflationIndex = ql.USCPI(False, cpiTS)
#last observed CPI level
fixing_rate = 252.0
baseZeroRate = 1.8
inflationIndex.addFixing(fixing_date, fixing_rate)
observationLag = ql.Period(lag, ql.Months)
zeroSwapHelpers = []
for date,rate in zciisData:
nextZeroSwapHelper = ql.ZeroCouponInflationSwapHelper(rate/100,observationLag,date,calendar,
convention,dayCounter,inflationIndex)
zeroSwapHelpers = zeroSwapHelpers + [nextZeroSwapHelper]
# the derived inflation curve
derived_inflation_curve = ql.PiecewiseZeroInflation(observationDate, calendar, dayCounter, observationLag,
inflationIndex.frequency(), inflationIndex.interpolated(),
baseZeroRate, yTS, zeroSwapHelpers,
1.0e-12, ql.Linear())
cpiTS.linkTo(derived_inflation_curve)
return inflationIndex, derived_inflation_curve, cpiTS, yTS
observation_date = ql.Date(17, 4, 2019)
calendar = ql.UnitedStates()
inflationIndex, derived_inflation_curve, cpiTS, yTS = build_inflation_term_structure(calendar, observation_date)
If I plot the inflationIndex zero rates, I get this:
I've now been checking the same problem and first of all I don't think you need that function ZeroCouponInflationSwapHelper at all.
Just to let you know I've perfectly replicated OpenRiskEngine (ORE)'s inflation curve which itself is built on QuantLib and the idea is quite simple.
compute base value I(0) which is the lagged CPI (this is supposedly your value 252.0),
compute CPI(t)=I(T)=I(0)*(1+quote)^T, where T = ZCIS expiry date, t is T - 3M
I'm not sure where you took I(0) from, but since a lag is present the I(0) is not the latest available CPI value. Instead I(0)=I(2019-04-17) is interpolated value of CPI(2019-01) and CPI(2019-02).
Also to build the CPI curve you don't need any interest rate yield curve at all because the ZCIS pays at maturity T a single cash flow: 'floating' (I(T)/I(0)-1) for 'fixed' (1+quote)^T-1 cash flows. If you equate these, you can back out the 'fair' I(T) which I used above.
Assuming your value I(0)=252.0 is correct, your CPI curve would look like this:
import QuantLib as ql
import pandas as pd
fixing_rate = 252.0
observation_date = ql.Date(17, 4, 2019)
zciisData = [(ql.Date(18,4,2020), 1.9948999881744385),
(ql.Date(18,4,2021), 1.9567999839782715),
(ql.Date(18,4,2022), 1.9566999673843384),
(ql.Date(18,4,2023), 1.9639999866485596),
(ql.Date(18,4,2024), 2.017400026321411),
(ql.Date(18,4,2025), 2.0074000358581543),
(ql.Date(18,4,2026), 2.0297999382019043),
(ql.Date(18,4,2027), 2.05430006980896),
(ql.Date(18,4,2028), 2.0873000621795654),
(ql.Date(18,4,2029), 2.1166999340057373),
(ql.Date(18,4,2031), 2.152100086212158),
(ql.Date(18,4,2034), 2.18179988861084),
(ql.Date(18,4,2039), 2.190999984741211),
(ql.Date(18,4,2044), 2.2016000747680664),
(ql.Date(18,4,2049), 2.193000078201294)]
fixing_dates = []
CPI_computed = []
for tenor, quote in zciisData:
fixing_dates.append(tenor - ql.Period('3M')) # this is 'fixing date' t
pay_date = ql.ActualActual().yearFraction(observation_date, tenor) # this is year fraction of 'pay date' T
CPI_computed.append(fixing_rate * (1+quote/100)**(pay_date))
results = pd.DataFrame({'date': pd.Series(fixing_dates).apply(ql.Date.to_date), 'CPI':CPI_computed})
display(results)
results.set_index('date')['CPI'].plot();

Basic pyephem code

I have a very simple code to get the longitude of the sun but when I compare the output to Astrolog and Astrodienst its incorrect, there is a 13 minute difference. I have not added Observer as I think default is midnight GMT (which is what I want). What am I doing wrong?
import ephem
start = ephem.date('2015/01/01')
end = ephem.date('2015/12/31')
f2 = open("Sun", 'w')
while start <= end:
sun = ephem.Sun(start)
ecl = ephem.Ecliptic(sun)
f2.write(str(ephem.date(start))+' '+ str(ecl.lon) +'\n')
start+=1
f2.close()
Example of results for 2015/12/30:
code - 2015/12/30 00:00:00 277:43:36.6
Astrodienst - 7°56'39 Cap
Thanks
The reason why the 13 minute difference is because of the epoch setting, when I added
sun = ephem.Sun(start, epoch = start)
the results were the same as swiss ephemeris.

Why is day of pandas date_range not what I specified?

Why is the first date not 4/19/1965? Why day 30 instead of 19?
dates = pd.date_range('1965-04-19', freq='6M', periods=3)
dates[0]
Timestamp('1965-04-30 00:00:00', offset='6M')
It looks like the default behavior for freq='M' is MonthEnd(), so
dates = pd.date_range('1965-04-19', periods=3, freq='6M')
dates
DatetimeIndex(['1965-04-30', '1965-10-31', '1966-04-30'], dtype='datetime64[ns]', freq='6M', tz=None)
This can be changed by setting freq = pd.tseries.offsets.DateOffset(months=6).
dates = pd.date_range('1965-04-19', periods=3, freq=pd.tseries.offsets.DateOffset(months=6))
dates
DatetimeIndex(['1965-04-19', '1965-10-19', '1966-04-19'], dtype='datetime64[ns]', freq='<DateOffset: kwds={'months': 6}>', tz=None)