Skip to content

Instantly share code, notes, and snippets.

@matthewdowney
Created January 24, 2023 17:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matthewdowney/be1c88c2d3d72312bd2bae5bf7788809 to your computer and use it in GitHub Desktop.
Save matthewdowney/be1c88c2d3d72312bd2bae5bf7788809 to your computer and use it in GitHub Desktop.
; # 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