Created
April 15, 2018 15:17
-
-
Save eleco/256e2ee9f0e619cf9e91dc25f5204062 to your computer and use it in GitHub Desktop.
An experiment in generating a random walk for the bitcoins prices
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.megalit; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Random; | |
import java.util.concurrent.Callable; | |
import java.util.concurrent.ExecutorService; | |
import java.util.concurrent.Executors; | |
import java.util.concurrent.Future; | |
import static java.lang.Runtime.*; | |
import static java.util.concurrent.Executors.newFixedThreadPool; | |
public class RandomWalk { | |
/** An experiment in generating a random walk for the bitcoins prices over nSimulations | |
* and comparing the cost/benefit of maintaining a 50/50 bitcoins/cash portfolio vs | |
* pure hodl strategy without reallocation | |
*/ | |
private static final int nSimulations=1000; | |
public static void main(String args[]) throws Exception { | |
ExecutorService executorPool = newFixedThreadPool((int) (getRuntime().availableProcessors())); | |
double avgRatio= 0; //ratio return with rebalance vs static strategy | |
final List<Callable<Double>> partitions = new ArrayList<Callable<Double>>(); | |
for (int i=0 ; i<nSimulations ; i++) { | |
partitions.add(() -> new GBMExperiment().run()); | |
} | |
List<Future<Double>> results = executorPool.invokeAll(partitions); | |
executorPool.shutdown(); | |
for(final Future<Double> ratio : results) { | |
avgRatio += ratio.get(); | |
} | |
System.out.println("avg ratio rebalance vs static:" + avgRatio/nSimulations); | |
} | |
} | |
class GBMExperiment { | |
public double run(){ | |
double T = 1.0; | |
double S0 = 5000; //initial price | |
double dt = 1.0/360.0; // Time step of one day | |
double yearlyVol= 20; | |
double yearlyDrift = 30; | |
double initialCash=5000; | |
double cash = initialCash; | |
double initialBitcoins = 1; | |
double bitcoins = initialBitcoins; | |
double fees = 0; | |
double lastPrice = S0; | |
for (double t = 0; t <= T*360; t += 1) { | |
double newPrice = lastPrice * generate_gbm_prices(yearlyDrift/100/360, yearlyVol/100/Math.sqrt(360), 1); | |
//System.out.println("t:" + t + " newPrice:" + newPrice + " ratio cash/bitcoins = " + cash/( bitcoins* lastPrice)); | |
lastPrice = newPrice; | |
double bitcoinValue = newPrice * bitcoins; | |
double rebalance = (cash+bitcoinValue)/2.0 - bitcoinValue; | |
if (Math.abs(rebalance) > 100) { | |
bitcoins+=(rebalance/lastPrice); | |
double fee = rebalance*5/100.0; | |
cash = cash- rebalance -fee; | |
fees+=fee; | |
} | |
} | |
System.out.println("with rebalancing: \n cash :" + cash + " bitcoins: " + bitcoins + " x " + lastPrice + | |
" = " + (bitcoins*lastPrice) + " total portfolio:" + (bitcoins*lastPrice + cash) + " fees total:" + fees); | |
System.out.println("without rebalancing: \n cash :" + initialCash + | |
" bitcoins: " + initialBitcoins + " x " + lastPrice + | |
" = " + (initialBitcoins*lastPrice) + | |
" total portfolio:" + (initialBitcoins*lastPrice + initialCash)); | |
//ratio rebalance vs static strategies | |
double ratio = (bitcoins*lastPrice+cash) / (initialBitcoins*lastPrice + initialCash); | |
return ratio; | |
} | |
static double generate_gbm_prices(double mu, double sigma, int dt) { | |
double w1 = new Random().nextGaussian() * Math.sqrt(dt); | |
double ito = (mu - Math.pow(sigma, 2) * .5) * dt + sigma * w1; | |
return Math.exp(ito); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment