-
-
Save matthewdowney/be1c88c2d3d72312bd2bae5bf7788809 to your computer and use it in GitHub Desktop.
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
; # Syncing atom state + long computations | |
{:nextjournal.clerk/visibility {:code :hide :result :hide}} | |
(ns ^::clerk/no-cache sync | |
(:require [nextjournal.clerk :as clerk]) | |
(:import (java.util Random))) | |
(def integer-input | |
{:var-from-def? true | |
:transform-fn (comp clerk/mark-presented | |
(clerk/update-val | |
(fn [{::clerk/keys [var-from-def]}] | |
{:var-name (symbol var-from-def) | |
:value @@var-from-def}))) | |
:render-fn | |
'(fn [{:keys [var-name value]}] | |
[:input | |
{:type :number | |
:value value | |
:class "px-3 py-3 placeholder-blueGray-300 text-blueGray-600 relative bg-white bg-white rounded text-sm border border-blueGray-300 outline-none focus:outline-none focus:ring w-full" | |
:on-input #(nextjournal.clerk.viewer/clerk-eval | |
(doto | |
`(reset! ~var-name (Integer/parseInt ~(.. % -target -value))) | |
println))}])}) | |
{:nextjournal.clerk/visibility {:code :fold :result :show}} | |
; For each $1 you bet, you win either $X or $0, with 50% probability, where X = | |
^{::clerk/viewer integer-input ::clerk/sync true} | |
(defonce payoff (atom 2)) | |
; A simulation of many portfolios making this bet a hundred times with 10% | |
; of their bankroll: | |
^{:nextjournal.clerk/visibility {:code :hide :result :hide}} | |
(do ;; Here follows some helper code for the simulation | |
(defn portfolio | |
([bankroll ^Random r] | |
(portfolio bankroll r 50 @payoff)) | |
([bankroll ^Random r winprob winpayoff] | |
(lazy-seq | |
(let [bet-size (max (* bankroll 0.10) 0) | |
bet-result (if (< (.nextDouble r) (/ winprob 100.0)) | |
(* winpayoff bet-size) | |
0)] | |
(cons bankroll | |
(portfolio | |
(-> bankroll (- bet-size) (+ bet-result)) | |
r winprob winpayoff)))))) | |
(defn medians [data] | |
(let [data (vec data)] | |
(apply mapv | |
(fn [& values-at-time] | |
(let [sorted (vec (sort values-at-time))] | |
(nth sorted (quot (count sorted) 2)))) | |
(map :y data)))) | |
(defn with-medians [data ms] | |
(conj | |
(mapv #(assoc % :showlegend false :opacity 0.25) data) | |
{:y ms | |
:showlegend true | |
:type "scatter" | |
:line {:width 3 :color "firebrick"} | |
:name "Median"})) | |
(def n-portfolios 100)) | |
^{:nextjournal.clerk/width :full} | |
(let [data (for [i (range n-portfolios)] | |
{:y (into [] (take 100) (portfolio 100 (Random. i))) | |
:opacity 0.15 | |
:type "scatter"}) | |
counting (completing (fn ([] 0) ([n _] (inc n)))) | |
n-lost (transduce | |
(comp | |
(map (comp peek :y)) | |
(filter #(< % 100))) | |
counting | |
data) | |
ms (medians data)] | |
(clerk/plotly | |
{:data (with-medians data ms) | |
:layout {:title (str "Betting 10%" | |
", median final bankroll " (biginteger (peek ms)) | |
", " n-lost " portfolios lost money") | |
:xaxis {:title "Bet #"} | |
:yaxis {:title "Bankroll" :type :log}}})) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment