Browse the docs
Example 13 of 13
Aframax tanker on time charter
Based on Project Finance-Class 5 Start.xlsm
A 70,000-tonne tanker bought for USD 60m and chartered out by the day. Charter days fall during dry-docks that grow longer with age, charter rates follow the market with a three-month lag, and the owner reports returns in dollars and rupees. Design example: written in the full v0.5 language. The compiler builds the working core today, so this one doesn't compile yet. Source: examples/design/ship/.
- Library
- A. Featured Models / L. Shipping (6 files)
- Timeline
- 36 months to delivery, 25-year life; operations monthly, financing quarterly
- Ship
- 70,000 t; capex USD 60m paid 10% / 10% / 70% / 10% at months 1, 13, 25 and 36
- Operations
- Charter rate forecast in real USD a day (15,457 in 2023), 3-month lag; daily costs USD 3,289; dry-dock 15, 25 and 35 days at ages 1, 5 and 15
- Finance
- Up to 90% debt, KIBOR 10% + 1%, 8 years, 1% upfront; WACC 7% (USD) and 14% (PKR)
- Rebuild shown
- 4 files, 74 lines
Where each sheet goes
| Workbook sheets | Rufineer |
|---|---|
| Input | inputs.rfn and the Charter rates and Dry-dock sheets |
| Operations - Monthly | operations.rfn on the monthly ruler |
| Financing - Quarterly | financing.rfn on the quarterly ruler |
| Rates and Oil, Interpolate | interpolate on the charter-rate curve |
| Debt Sculpting, Taxes and NOL | financing.rfn |
Source 4 files shown, 74 lines
model "Aframax Tanker" {
currency USD
currency PKR
data "tanker_inputs.xlsx"
}
timeline {
start 2023-01-01
construction 36m // build to delivery
operations 25y
ruler monthly month
ruler quarterly quarter
}
fx PKR/USD = ppp(178, local: inputs.macro.pkr_cpi, foreign: inputs.macro.usd_cpi)table charter_curve: USD/d // Year | Time-charter rate, real
table drydock_days: d // Ship age | Days: 1 → 15, 5 → 25, 15 → 35
table daily_costs: USD/d // Victualling 242, stores 357, wages 1,664, sundries 218,
// lubes 339, other 256, repairs 212
table macro { rows year; columns usd_cpi: %/y "USD inflation", pkr_cpi: %/y "PKR inflation" }
table drydocks { rows dock; columns start: date "Start", age: y "Ship age" }
inputs "Ship" {
capacity = 70_000 t
capex = 60_000_000 USD
spend = { 1: 10, 13: 10, 25: 70, 36: 10 } % // by construction month
life = 25y
charter_lag = 3m
commission = 2.5 %
insurance_bands = { ..10y: 0.2, 10y..15y: 0.3, 15y..: 0.4 } %/y // of original cost
tonnage_tax = 1 USD/t/y
depreciation = 4 %/y
}
inputs "Finance" {
max_gearing = 90 %
kibor = 10 %/y
spread = 1 %/y
tenor = 8y
upfront_fee = 1 %
wacc_usd = 7 %/y
wacc_pkr = 14 %/y
}module ship "Operations" on monthly {
age: y = operations.year - 1 + operations.period / 12
/// Dry-docks: longer as the ship ages, and they can run across month ends
period drydock[k] = inputs.drydocks[k].start for inputs.drydock_days[inputs.drydocks[k].age]
off_hire: d = sum(overlap(drydock[*]))
charter_days: d = (period.days - off_hire) | during operations
rate: USD/d = interpolate(inputs.charter_curve, year)
| grow inputs.macro.usd_cpi | lag inputs.charter_lag
revenue: USD = charter_days * rate * (1 - inputs.commission)
running_costs: USD = sum(inputs.daily_costs) * period.days | grow inputs.macro.usd_cpi
insurance: USD = inputs.capex * bands(age, inputs.insurance_bands)
tonnage_tax: USD = inputs.capacity * inputs.tonnage_tax | during operations
ebitda: USD = revenue - running_costs - insurance - tonnage_tax
capex: USD = inputs.capex * inputs.spend[construction.period] | during construction
}module finance "Financing" on quarterly {
capex: USD = ship.capex // summed into quarters
/// The loan is in rupees; the ship earns dollars
balance loan: PKR {
+ inputs.max_gearing * capex in PKR
- principal
}
period tenor = operations.start for inputs.tenor
interest: PKR = loan.opening * (inputs.kibor + inputs.spread)
principal: PKR = clamp((ship.ebitda in PKR) / 1.30 x - interest, 0, loan.opening) | during tenor
fees: PKR = inputs.upfront_fee * inputs.max_gearing * inputs.capex in PKR
| at construction.start
debt_service: USD = (interest + principal + fees) in USD
}
module returns "Returns" {
project_cash: USD = ship.ebitda - finance.capex
npv_usd = xnpv(project_cash, rate: inputs.wacc_usd)
npv_pkr = xnpv(project_cash in PKR, rate: inputs.wacc_pkr)
project_irr = xirr(project_cash) // 11.0% in the workbook
}What this model needed from the language
- Days inside a period.
overlap(drydock[*])counts the dry-dock days that fall in each month, including one that runs across a month end. - A lag. Charter rates reset three months after the market:
| lag 3m. - Age bands. Insurance steps up at 10 and 15 years:
bands(age, …). - A rupee loan against dollar earnings, with returns in both currencies.