Skip to content

A go library to help rebalancing your portfolio assets to match a target index

Notifications You must be signed in to change notification settings

pdbrito/rebalancer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

82 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rebalancer

Build Status GoDoc Go Report Card Codecov

Rebalancer provides tools to help you with rebalancing your assets.

Examples

Rebalancing

Let's assume the current price of 1 BTC is $5000 and the current price of 1 ETH is $200.

First set the global pricelist to reflect these prices:

err := SetPricelist(Pricelist{
	"ETH": decimal.NewFromFloat(200),
	"BTC": decimal.NewFromFloat(5000),
})

if err != nil {
	log.Fatalf("unexpected error whilst setting pricelist: %v", err)
}

If your assets are 20 ETH and 0.5 BTC, you can model your account like this:

account, err := NewAccount(Portfolio{
	"ETH": decimal.NewFromFloat(20),
	"BTC": decimal.NewFromFloat(0.5),
})

if err != nil {
	log.Fatalf("unexpected error whilst creating account: %v", err)
}

The current value of all your assets is:

0.5 x 5000 + 20 x 200 = 6500

The current percentage of each asset is:

ETH = 20 * 200 / 6500 = 0.615384...
BTC = 0.5 * 5000 / 6500 = 0.384615...

If you wanted to change this to a 50/50 split, we need to model a target index:

targetIndex := Index{
	"ETH": decimal.NewFromFloat(0.5),
	"BTC": decimal.NewFromFloat(0.5),
})

You can then pass targetIndex to your account.Rebalance() and you'll receive
the trades necessary to rebalance your portfolio as a map[Asset]Trade.

requiredTrades, err := account.Rebalance(targetIndex)

if err != nil {
	log.Fatalf("unexpected error whilst rebalancing account: %v", err)
}

for asset, trade := range requiredTrades {
	fmt.Printf("%s %s %s\n", trade.Action, trade.Amount, asset)
}

// Unordered output:
// sell 3.75 ETH
// buy 0.15 BTC

Rebalancing into new assets

You can also rebalance your current portfolio into other new assets, as long as these new assets are included in the global pricelist:

err := SetPricelist(Pricelist{
	"ETH":  decimal.NewFromFloat(200),
	"BTC":  decimal.NewFromFloat(2000),
	"IOTA": decimal.NewFromFloat(0.3),
	"BAT":  decimal.NewFromFloat(0.12),
	"XLM":  decimal.NewFromFloat(0.2),
})

if err != nil {
	log.Fatalf("unexpected error whilst setting pricelist: %v", err)
}

account, err := NewAccount(Portfolio{
	"ETH": decimal.NewFromFloat(42),
})

if err != nil {
	log.Fatalf("unexpected error whilst creating account: %v", err)
}

targetIndex := Index{
	"ETH":  decimal.NewFromFloat(0.2),
	"BTC":  decimal.NewFromFloat(0.2),
	"IOTA": decimal.NewFromFloat(0.2),
	"BAT":  decimal.NewFromFloat(0.2),
	"XLM":  decimal.NewFromFloat(0.2),
}

requiredTrades, err := account.Rebalance(targetIndex)

if err != nil {
	log.Fatalf("unexpected error whilst rebalancing account: %v", err)
}

for asset, trade := range requiredTrades {
	fmt.Printf("%s %s %s\n", trade.Action, trade.Amount, asset)
}

// Unordered output:
// sell 33.6 ETH
// buy 0.84 BTC
// buy 5600 IOTA
// buy 14000 BAT
// buy 8400 XLM

About

A go library to help rebalancing your portfolio assets to match a target index

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages