Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,15 +1,17 @@
|
|
1 |
from collections import defaultdict
|
2 |
|
3 |
-
|
4 |
import streamlit as st
|
5 |
import streamlit.components.v1 as components
|
6 |
import plotly.graph_objects as go
|
7 |
import plotly.express as px
|
8 |
import numpy as np
|
|
|
9 |
|
10 |
|
11 |
st.set_page_config(page_title='Can you be truly random ?', layout = 'wide', page_icon = 'favicon.jpg', initial_sidebar_state = 'auto')
|
12 |
|
|
|
13 |
|
14 |
|
15 |
# Custom CSS to styles
|
@@ -23,7 +25,7 @@ st.markdown("""
|
|
23 |
""", unsafe_allow_html=True)
|
24 |
|
25 |
|
26 |
-
|
27 |
|
28 |
def set_state(x):
|
29 |
if x == 1: st.toast('The journey begins!', icon='π')
|
@@ -39,6 +41,7 @@ def reset_game():
|
|
39 |
st.session_state.pnl = [0]
|
40 |
st.session_state.min = [0]
|
41 |
st.session_state.max = [0]
|
|
|
42 |
|
43 |
if 'stage' not in st.session_state:
|
44 |
reset_game()
|
@@ -52,73 +55,43 @@ if st.session_state.stage == 0:
|
|
52 |
|
53 |
st.markdown(f'You will be presented with {st.session_state.n_buttons} buttons to randomly choose from')
|
54 |
|
55 |
-
|
|
|
|
|
|
|
|
|
56 |
st.markdown(f"If I get it right, I earn {st.session_state.n_buttons-1} point(s), otherwise you earn 1 point")
|
57 |
-
st.markdown(f
|
|
|
58 |
|
59 |
|
60 |
|
61 |
-
|
62 |
-
# def get_prev_seqs(history):
|
63 |
-
# # st.write(history)
|
64 |
-
|
65 |
-
# seqs = []
|
66 |
-
# for h in range(max_history+1):
|
67 |
-
# if len(history) >= h:
|
68 |
-
# previous_seq = ''.join(history[-h:]) if h > 0 else ""
|
69 |
-
# # st.write(previous_seq)
|
70 |
-
# seqs.append(previous_seq) # from small to largest
|
71 |
-
# return seqs
|
72 |
-
|
73 |
-
# def refresh_preds():
|
74 |
-
# played = st.session_state.history[-1]
|
75 |
-
# seqs = get_prev_seqs(st.session_state.history[:-1])
|
76 |
-
# for seq in seqs:
|
77 |
-
# # st.write(f'"{seq}"',played)
|
78 |
-
# st.session_state.preds[seq][played] += 1
|
79 |
-
|
80 |
-
def make_pred(max_history=max_history,alpha=0.5):
|
81 |
history = st.session_state.history
|
82 |
|
83 |
denominator = 0
|
84 |
scores = {str(i):0 for i in range(st.session_state.n_buttons)}
|
85 |
recent = np.array(history[-max_history:])
|
|
|
86 |
for i in range(1,len(history)):
|
87 |
past = np.array(history[-i-max_history:-i])
|
88 |
|
89 |
played = history[-i]
|
90 |
decay = np.exp(-alpha*np.linspace(1,0,len(past)))
|
91 |
-
|
|
|
92 |
weight = len(history)/(len(history)+i) * similarity
|
93 |
scores[played] += weight
|
94 |
denominator += weight
|
|
|
|
|
95 |
if not denominator:
|
96 |
-
return get_random_play()
|
97 |
result = {str(i):scores[str(i)]/denominator for i in range(st.session_state.n_buttons)}
|
98 |
-
return result
|
99 |
|
100 |
def get_random_play():
|
101 |
return {str(i):1/st.session_state.n_buttons for i in range(st.session_state.n_buttons)}
|
102 |
-
|
103 |
-
# def make_pred():
|
104 |
-
# seqs = get_prev_seqs(st.session_state.history)
|
105 |
-
# # st.write('seqs',seqs)
|
106 |
-
# scores = defaultdict(float)
|
107 |
-
# denominator = 0
|
108 |
-
# for i,seq in enumerate(seqs):
|
109 |
-
# weight = (i+1)**2
|
110 |
-
# preds = st.session_state.preds[seq]
|
111 |
-
# total = sum(preds.values())
|
112 |
-
|
113 |
-
# if total:
|
114 |
-
# for played,value in preds.items():
|
115 |
-
# scores[played] += weight*value/total
|
116 |
-
# denominator += weight
|
117 |
-
# if denominator:
|
118 |
-
# scores = {played:value/denominator for played,value in scores.items()}
|
119 |
-
# return scores
|
120 |
-
# else:
|
121 |
-
# return get_random_play()
|
122 |
|
123 |
|
124 |
def update_pnl(user_win):
|
@@ -148,22 +121,45 @@ def compute_perf():
|
|
148 |
std = data.std()
|
149 |
win = (data>0).mean()
|
150 |
sharpe = perf / std
|
151 |
-
return
|
152 |
-
|
|
|
|
|
|
|
|
|
153 |
|
154 |
if st.session_state.stage == 1:
|
155 |
-
pred = make_pred()
|
|
|
156 |
choice = max(pred,key=pred.get)
|
157 |
|
158 |
cols = st.columns(st.session_state.n_buttons)
|
159 |
for i,col in enumerate(cols):
|
160 |
col.button(str(i),on_click=user_select, args=[str(i),choice],
|
161 |
use_container_width=True)
|
162 |
-
|
163 |
-
st.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
164 |
fig = px.line(st.session_state.pnl)
|
165 |
fig.update_layout(showlegend=False)
|
166 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
167 |
|
168 |
st.button('Start over', on_click=reset_game, args=[],
|
169 |
use_container_width=True)
|
|
|
1 |
from collections import defaultdict
|
2 |
|
3 |
+
import seaborn as sns
|
4 |
import streamlit as st
|
5 |
import streamlit.components.v1 as components
|
6 |
import plotly.graph_objects as go
|
7 |
import plotly.express as px
|
8 |
import numpy as np
|
9 |
+
import pandas as pd
|
10 |
|
11 |
|
12 |
st.set_page_config(page_title='Can you be truly random ?', layout = 'wide', page_icon = 'favicon.jpg', initial_sidebar_state = 'auto')
|
13 |
|
14 |
+
cm = sns.light_palette("green", as_cmap=True)
|
15 |
|
16 |
|
17 |
# Custom CSS to styles
|
|
|
25 |
""", unsafe_allow_html=True)
|
26 |
|
27 |
|
28 |
+
|
29 |
|
30 |
def set_state(x):
|
31 |
if x == 1: st.toast('The journey begins!', icon='π')
|
|
|
41 |
st.session_state.pnl = [0]
|
42 |
st.session_state.min = [0]
|
43 |
st.session_state.max = [0]
|
44 |
+
st.session_state.max_history = 10
|
45 |
|
46 |
if 'stage' not in st.session_state:
|
47 |
reset_game()
|
|
|
55 |
|
56 |
st.markdown(f'You will be presented with {st.session_state.n_buttons} buttons to randomly choose from')
|
57 |
|
58 |
+
|
59 |
+
st.session_state.max_history = st.slider(label="How much memory can I use?", min_value=2, max_value=20,value=10)
|
60 |
+
st.markdown(f"At each round, I will try to predict which button you click")
|
61 |
+
st.markdown(f"I will examine {st.session_state.max_history}-long sequences you played in the past")
|
62 |
+
st.markdown('This will help me make a guess')
|
63 |
st.markdown(f"If I get it right, I earn {st.session_state.n_buttons-1} point(s), otherwise you earn 1 point")
|
64 |
+
st.markdown(f'This is a fair game, as you have {(1-1/st.session_state.n_buttons):.0%} chances of winning')
|
65 |
+
st.subheader(f"Play as long as you want and try to beat me!")
|
66 |
|
67 |
|
68 |
|
69 |
+
def make_pred(max_history=st.session_state.max_history,alpha=0.5):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
history = st.session_state.history
|
71 |
|
72 |
denominator = 0
|
73 |
scores = {str(i):0 for i in range(st.session_state.n_buttons)}
|
74 |
recent = np.array(history[-max_history:])
|
75 |
+
data = []
|
76 |
for i in range(1,len(history)):
|
77 |
past = np.array(history[-i-max_history:-i])
|
78 |
|
79 |
played = history[-i]
|
80 |
decay = np.exp(-alpha*np.linspace(1,0,len(past)))
|
81 |
+
same = past == recent[-len(past):]
|
82 |
+
similarity = (same*decay).sum() / decay.sum()
|
83 |
weight = len(history)/(len(history)+i) * similarity
|
84 |
scores[played] += weight
|
85 |
denominator += weight
|
86 |
+
if similarity > 0.5:
|
87 |
+
data.append([played,similarity,weight,i] + [None]* (max_history-len(past)) +list(same))
|
88 |
if not denominator:
|
89 |
+
return get_random_play(),data
|
90 |
result = {str(i):scores[str(i)]/denominator for i in range(st.session_state.n_buttons)}
|
91 |
+
return result, data
|
92 |
|
93 |
def get_random_play():
|
94 |
return {str(i):1/st.session_state.n_buttons for i in range(st.session_state.n_buttons)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
|
96 |
|
97 |
def update_pnl(user_win):
|
|
|
121 |
std = data.std()
|
122 |
win = (data>0).mean()
|
123 |
sharpe = perf / std
|
124 |
+
return win,sharpe
|
125 |
+
else:
|
126 |
+
return 0,0
|
127 |
+
|
128 |
+
|
129 |
+
|
130 |
|
131 |
if st.session_state.stage == 1:
|
132 |
+
pred,data = make_pred()
|
133 |
+
|
134 |
choice = max(pred,key=pred.get)
|
135 |
|
136 |
cols = st.columns(st.session_state.n_buttons)
|
137 |
for i,col in enumerate(cols):
|
138 |
col.button(str(i),on_click=user_select, args=[str(i),choice],
|
139 |
use_container_width=True)
|
140 |
+
|
141 |
+
col1,col2 = st.columns(st.session_state.n_buttons)
|
142 |
+
|
143 |
+
win,sharpe = compute_perf()
|
144 |
+
if sharpe > 0.1:
|
145 |
+
emoticon = "π"
|
146 |
+
elif sharpe < 0:
|
147 |
+
emoticon = "π"
|
148 |
+
else:
|
149 |
+
emoticon = "π§ "
|
150 |
+
text = f'%age win={win:.0%} Sharpe={sharpe:.3f} {emoticon}'
|
151 |
+
col1.subheader('My earnings so far...')
|
152 |
+
col1.write(text)
|
153 |
fig = px.line(st.session_state.pnl)
|
154 |
fig.update_layout(showlegend=False)
|
155 |
+
fig.update_layout(xaxis={'visible': True, 'showticklabels': False})
|
156 |
+
col1.plotly_chart(fig, use_container_width=True)
|
157 |
+
|
158 |
+
cols = ['you_played','similarity','weight','how_long_ago'] + [f'same_{i}' for i in range(st.session_state.max_history)]
|
159 |
+
data = pd.DataFrame(data,columns=cols).set_index('how_long_ago').sort_values('weight',ascending=False)[:10]
|
160 |
+
col2.subheader(f'In the past, you played')
|
161 |
+
col2.dataframe(data.style.background_gradient(cmap=cm), use_container_width=True)
|
162 |
+
col2.subheader(f'I play {choice}, p={pred[choice]:.0%}')
|
163 |
|
164 |
st.button('Start over', on_click=reset_game, args=[],
|
165 |
use_container_width=True)
|