Carry trade calculator
Borrow 100,000 at 0.5%, invest it at 4.5%, lose 1.2% on the currency, and the carry trade still earns 2,746, a 2.746% net return. Enter the four numbers of any FX carry to see whether the rate gap survives the currency move. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Borrowed amount
- 100,000
- Funding rate
- 0.5
- Investment rate
- 4.5
- Exchange rate change
- -1.2
- Interest differential
- 4
- Funding cost
- 500
- Investment proceeds
- 103,246
- Loan repayment
- 100,500
A carry trade borrows in a low-yielding funding currency and invests the proceeds in a higher-yielding currency, hoping the interest differential more than offsets any adverse move in the exchange rate. This carry trade calculator takes the four numbers that define a one-period FX carry: the borrowed amount in funding-currency units, the funding currency interest rate as a percent, the investment currency interest rate as a percent, and the percent change in the investment currency versus the funding currency over the same holding period. It returns the profit in funding-currency units and the net return as a percent of the borrowed notional, using the multiplicative identity that compounds investment yield with the FX move and then subtracts the funding cost.
How carry trade profit and net return are computed
A currency carry trade is a funded position: you borrow an amount B in the funding currency at rate rf, convert into the investment currency, earn rate ri, convert back after the exchange rate has moved, and repay the funding loan. Let dS be the percent change of the investment currency versus the funding currency over that same holding period, so a positive dS means the investment currency appreciated and you convert back more funding units.
The one-period multiplicative identity used here is profit equals B times the quantity (one plus ri over one hundred) times (one plus dS over one hundred) minus (one plus rf over one hundred). Net return, the headline field, is one hundred times profit divided by B, so it is a percent of the borrowed notional and lives in the same units as the three rate inputs.
That closed form keeps the cross term between investment yield and the FX move; the linear classroom shortcut ri minus rf plus dS drops that product and is only a first-order approximation. Interest differential is returned as ri minus rf so you can see the carry you were paid before FX. Funding cost is B times rf over one hundred, loan repayment is B times one plus rf over one hundred, and investment proceeds are B marked through both the investment factor and the FX factor.
When dS is negative the investment currency depreciated: proceeds shrink, and a large enough depreciation turns a positive carry into a loss even though ri still exceeds rf. When dS is zero the result collapses to a pure interest-rate differential on the notional. Negative policy rates are valid inputs because several funding currencies have printed below zero; they simply reduce the repayment factor.
Where a carry trade calculator earns its keep
FX desks, macro funds, and treasury teams use a carry trade calculator to turn a quote sheet of two policy rates and a realised or scenario FX move into a P&L and a percent net return on the funded notional, without opening a spreadsheet that silently annualises a three-month rate. Classroom courses on uncovered interest parity need a deterministic oracle that does not drop the multiplicative cross term and that rejects a non-positive borrowed amount instead of returning infinity or a NaN. Failed validation does not consume balance.
Compare the linear shortcut against this multiplicative result on large FX moves: the gap is the cross term, and that is often the difference between a desk estimate and a settlement number.
What you can do with it
Pre-trade FX carry P&L
Turn two period rates and a scenario exchange-rate change into profit and net return on the funded notional before you put on a short-funding long-target currency pair.
Classroom uncovered interest parity
Show students that carry is the interest differential plus the FX move, with the multiplicative cross term kept, and that a non-positive borrowed amount is invalid rather than a silent NaN.
FAQ
What happens if the borrowed amount is zero or negative?
A carry trade with a non-positive notional is not a return problem and is not billed.
Are the interest rates annual, or for the holding period?
If your quotes are annual and the trade lasts three months, scale the two rates to that period before you send them.
Can a carry trade lose money if the investment rate is higher?
Yes. If the investment currency weakens enough against the funding currency during the holding period, the smaller proceeds can wipe out the interest gap and turn the trade into a loss, even though the investment rate still exceeds the funding rate.
Why isn't the return just the rate gap plus the currency move?
That shortcut leaves out the cross effect between the investment yield and the currency move, so it is only an approximation. The calculator compounds the two before subtracting the funding cost, which is why the example shows 2.746%.
Can I enter negative interest rates?
Yes. Several funding currencies have had policy rates below zero, so negative rates are accepted for either currency. A negative funding rate simply lowers what you must repay on the loan.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/fin/carry-trade \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"borrowed_amount":100000,"funding_rate":0.5,"investment_rate":4.5,"exchange_rate_change":-1.2}'const res = await fetch("https://api.kit.forhosting.com/fin/carry-trade", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"borrowed_amount": 100000,
"funding_rate": 0.5,
"investment_rate": 4.5,
"exchange_rate_change": -1.2
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/fin/carry-trade",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"borrowed_amount": 100000,
"funding_rate": 0.5,
"investment_rate": 4.5,
"exchange_rate_change": -1.2
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/fin/carry-trade", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"borrowed_amount":100000,"funding_rate":0.5,"investment_rate":4.5,"exchange_rate_change":-1.2}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"borrowed_amount":100000,"funding_rate":0.5,"investment_rate":4.5,"exchange_rate_change":-1.2}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/fin/carry-trade", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"borrowed_amount": 100000,
"funding_rate": 0.5,
"investment_rate": 4.5,
"exchange_rate_change": -1.2
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "fin.carry_trade",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_abs_amount | 1000000000000000 |
max_abs_rate | 1000000 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
A borrowed amount that is not positive is rejected as invalid_input rather than silently producing a meaningless return.
Input contract, positive notional, and error behaviour
The three rate fields must describe the same horizon as each other and as the FX move; if your rates are annual and the trade lasts three months, scale them before you call. POST a JSON body with four required finite numbers. borrowed_amount is the notional you fund in the funding currency and must be strictly greater than zero; a zero, negative, missing, or non-finite notional fails with invalid_input naming borrowed_amount and is not billed, because a carry with nothing borrowed is not a return problem. funding_rate is the interest rate of the borrowed currency for the holding period as a percent: use 0.5 for one half of one percent, not 0.005, and negative values are accepted for negative-rate funding currencies. investment_rate is the interest rate of the target currency for the same period as a percent, with the same sign convention. exchange_rate_change is the percent change of the investment currency versus the funding currency: positive appreciation, negative depreciation. Aliases amount, notional, principal, and borrow are accepted for borrowed_amount; funding_currency_rate, borrow_rate, and rf for funding_rate; investment_currency_rate, invest_rate, and ri for investment_rate; fx_change, fx_return, currency_change, and delta_s for exchange_rate_change. On success the body echoes the four inputs and returns interest_differential, funding_cost, investment_proceeds, loan_repayment, profit, net_return, and a short formula string. Example: one hundred thousand borrowed at 0.5 percent, invested at 4.5 percent, with the investment currency down 1.2 percent, is a typical short-yen long-commodity-currency sketch and yields a stable twelve-decimal net_return you can pin in tests because the module is pure and deterministic.
Where a carry trade calculator earns its keep
Backtests and scenario engines batch many combinations of borrowed_amount, funding_rate, investment_rate, and exchange_rate_change through the JSON API when they already know the rates and the FX move and only need the identity applied without drift. Keep requests small, pin the rounded profit and net_return in tests, and you get reproducible carry arithmetic for widgets, notebooks, and edge workers without standing up a full portfolio system of your own.
Integration use cases
Scenario and backtest overlay
Batch known rate pairs and realised FX changes through the API to mark a simple funded carry overlay without a spreadsheet annualising the horizon by accident.
Technical questions
How is carry trade profit and net return calculated?
Profit is borrowed_amount times ((1 + investment_rate/100) times (1 + exchange_rate_change/100) minus (1 + funding_rate/100)). Net return is 100 times profit divided by borrowed_amount, as a percent of the funded notional.
What does a negative exchange_rate_change mean?
The investment currency depreciated against the funding currency over the holding period, so you convert back fewer funding units. A large enough depreciation can wipe out a positive interest differential.
What does the carry trade calculator cost?
The browser tool is free. API requests use prepaid balance at $0.002 per successful call; invalid input is not billed.