Skip to content

Instantly share code, notes, and snippets.

@eleco
Created April 15, 2018 15:17
Show Gist options
  • Save eleco/256e2ee9f0e619cf9e91dc25f5204062 to your computer and use it in GitHub Desktop.
Save eleco/256e2ee9f0e619cf9e91dc25f5204062 to your computer and use it in GitHub Desktop.
An experiment in generating a random walk for the bitcoins prices
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