cyberosa
commited on
Commit
·
6154c13
1
Parent(s):
52d1750
correcting kl_div parameters and new graph for winning perc
Browse files- app.py +10 -0
- data/closed_markets_div.parquet +2 -2
- notebooks/closed_markets.ipynb +106 -0
- scripts/closed_markets_divergence.py +4 -4
- scripts/metrics.py +82 -0
- tabs/trader_plots.py +22 -0
app.py
CHANGED
@@ -8,6 +8,7 @@ import logging
|
|
8 |
from scripts.metrics import (
|
9 |
compute_weekly_metrics_by_market_creator,
|
10 |
compute_weekly_metrics_by_trader_type,
|
|
|
11 |
)
|
12 |
from tabs.trader_plots import (
|
13 |
plot_trader_metrics_by_market_creator,
|
@@ -15,6 +16,7 @@ from tabs.trader_plots import (
|
|
15 |
default_trader_metric,
|
16 |
trader_metric_choices,
|
17 |
get_metrics_text,
|
|
|
18 |
)
|
19 |
|
20 |
from tabs.market_plots import plot_kl_div_per_market
|
@@ -112,6 +114,9 @@ print(weekly_metrics_by_market_creator.head())
|
|
112 |
weekly_metrics_by_trader_type = compute_weekly_metrics_by_trader_type(
|
113 |
trader_agents_data
|
114 |
)
|
|
|
|
|
|
|
115 |
with demo:
|
116 |
gr.HTML("<h1>Trader agents monitoring dashboard </h1>")
|
117 |
gr.Markdown(
|
@@ -195,5 +200,10 @@ with demo:
|
|
195 |
kl_div_plot = plot_kl_div_per_market(closed_markets=closed_markets)
|
196 |
with gr.Column(scale=1):
|
197 |
metrics_text = get_metrics_text()
|
|
|
|
|
|
|
|
|
|
|
198 |
|
199 |
demo.queue(default_concurrency_limit=40).launch()
|
|
|
8 |
from scripts.metrics import (
|
9 |
compute_weekly_metrics_by_market_creator,
|
10 |
compute_weekly_metrics_by_trader_type,
|
11 |
+
compute_winning_metrics_by_trader,
|
12 |
)
|
13 |
from tabs.trader_plots import (
|
14 |
plot_trader_metrics_by_market_creator,
|
|
|
16 |
default_trader_metric,
|
17 |
trader_metric_choices,
|
18 |
get_metrics_text,
|
19 |
+
plot_winning_metric_per_trader,
|
20 |
)
|
21 |
|
22 |
from tabs.market_plots import plot_kl_div_per_market
|
|
|
114 |
weekly_metrics_by_trader_type = compute_weekly_metrics_by_trader_type(
|
115 |
trader_agents_data
|
116 |
)
|
117 |
+
weekly_winning_metrics = compute_winning_metrics_by_trader(
|
118 |
+
trader_agents_data=trader_agents_data
|
119 |
+
)
|
120 |
with demo:
|
121 |
gr.HTML("<h1>Trader agents monitoring dashboard </h1>")
|
122 |
gr.Markdown(
|
|
|
200 |
kl_div_plot = plot_kl_div_per_market(closed_markets=closed_markets)
|
201 |
with gr.Column(scale=1):
|
202 |
metrics_text = get_metrics_text()
|
203 |
+
with gr.TabItem("🎖️Weekly winning trades % per trader"):
|
204 |
+
with gr.Row():
|
205 |
+
gr.Markdown("# Winning trades percentage from weekly trades by trader")
|
206 |
+
with gr.Row():
|
207 |
+
winning_metric = plot_winning_metric_per_trader(weekly_winning_metrics)
|
208 |
|
209 |
demo.queue(default_concurrency_limit=40).launch()
|
data/closed_markets_div.parquet
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
-
size
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:8d2583a54d7d4b38e51c2bf1e808a710e6a4b232009b5ae8917ce0534b045d94
|
3 |
+
size 48882
|
notebooks/closed_markets.ipynb
CHANGED
@@ -1455,6 +1455,112 @@
|
|
1455 |
"source": [
|
1456 |
"len(markets_div)"
|
1457 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1458 |
}
|
1459 |
],
|
1460 |
"metadata": {
|
|
|
1455 |
"source": [
|
1456 |
"len(markets_div)"
|
1457 |
]
|
1458 |
+
},
|
1459 |
+
{
|
1460 |
+
"cell_type": "code",
|
1461 |
+
"execution_count": 1,
|
1462 |
+
"metadata": {},
|
1463 |
+
"outputs": [],
|
1464 |
+
"source": [
|
1465 |
+
"import numpy as np\n",
|
1466 |
+
"import math"
|
1467 |
+
]
|
1468 |
+
},
|
1469 |
+
{
|
1470 |
+
"cell_type": "code",
|
1471 |
+
"execution_count": 2,
|
1472 |
+
"metadata": {},
|
1473 |
+
"outputs": [],
|
1474 |
+
"source": [
|
1475 |
+
"def kl_divergence(p, q):\n",
|
1476 |
+
" \"\"\"\n",
|
1477 |
+
" Compute KL divergence for a single sample with two probabilities.\n",
|
1478 |
+
"\n",
|
1479 |
+
" :param p: First probability (true distribution)\n",
|
1480 |
+
" :param q: Second probability (approximating distribution)\n",
|
1481 |
+
" :return: KL divergence value\n",
|
1482 |
+
" \"\"\"\n",
|
1483 |
+
" # Ensure probabilities sum to 1\n",
|
1484 |
+
" p = np.array([p, 1 - p])\n",
|
1485 |
+
" q = np.array([q, 1 - q])\n",
|
1486 |
+
"\n",
|
1487 |
+
" # Avoid division by zero\n",
|
1488 |
+
" epsilon = 1e-10\n",
|
1489 |
+
" q = np.clip(q, epsilon, 1 - epsilon)\n",
|
1490 |
+
"\n",
|
1491 |
+
" # Compute KL divergence\n",
|
1492 |
+
" kl_div = np.sum(p * np.log(p / q))\n",
|
1493 |
+
"\n",
|
1494 |
+
" return kl_div"
|
1495 |
+
]
|
1496 |
+
},
|
1497 |
+
{
|
1498 |
+
"cell_type": "code",
|
1499 |
+
"execution_count": 3,
|
1500 |
+
"metadata": {},
|
1501 |
+
"outputs": [
|
1502 |
+
{
|
1503 |
+
"data": {
|
1504 |
+
"text/plain": [
|
1505 |
+
"3.791663620863367"
|
1506 |
+
]
|
1507 |
+
},
|
1508 |
+
"execution_count": 3,
|
1509 |
+
"metadata": {},
|
1510 |
+
"output_type": "execute_result"
|
1511 |
+
}
|
1512 |
+
],
|
1513 |
+
"source": [
|
1514 |
+
"p = 0.8145\n",
|
1515 |
+
"q = 1.0\n",
|
1516 |
+
"kl_divergence(p,q)"
|
1517 |
+
]
|
1518 |
+
},
|
1519 |
+
{
|
1520 |
+
"cell_type": "code",
|
1521 |
+
"execution_count": 6,
|
1522 |
+
"metadata": {},
|
1523 |
+
"outputs": [
|
1524 |
+
{
|
1525 |
+
"data": {
|
1526 |
+
"text/plain": [
|
1527 |
+
"0.16397451204513597"
|
1528 |
+
]
|
1529 |
+
},
|
1530 |
+
"execution_count": 6,
|
1531 |
+
"metadata": {},
|
1532 |
+
"output_type": "execute_result"
|
1533 |
+
}
|
1534 |
+
],
|
1535 |
+
"source": [
|
1536 |
+
"p = 0.99\n",
|
1537 |
+
"q = 0.8145\n",
|
1538 |
+
"kl_divergence(p, q)"
|
1539 |
+
]
|
1540 |
+
},
|
1541 |
+
{
|
1542 |
+
"cell_type": "code",
|
1543 |
+
"execution_count": 5,
|
1544 |
+
"metadata": {},
|
1545 |
+
"outputs": [
|
1546 |
+
{
|
1547 |
+
"name": "stdout",
|
1548 |
+
"output_type": "stream",
|
1549 |
+
"text": [
|
1550 |
+
"KL divergence: 0.16397451204513597\n"
|
1551 |
+
]
|
1552 |
+
}
|
1553 |
+
],
|
1554 |
+
"source": [
|
1555 |
+
"from scipy.special import kl_div\n",
|
1556 |
+
"\n",
|
1557 |
+
"# For multiple probabilities\n",
|
1558 |
+
"p = np.array([0.99, 0.01])\n",
|
1559 |
+
"q = np.array([0.8145, 0.1855])\n",
|
1560 |
+
"\n",
|
1561 |
+
"kl = np.sum(kl_div(p, q))\n",
|
1562 |
+
"print(f\"KL divergence: {kl}\")"
|
1563 |
+
]
|
1564 |
}
|
1565 |
],
|
1566 |
"metadata": {
|
scripts/closed_markets_divergence.py
CHANGED
@@ -164,13 +164,13 @@ def market_KL_divergence(market_row: pd.DataFrame) -> float:
|
|
164 |
"""Function to compute the divergence based on the formula
|
165 |
Formula in https://en.wikipedia.org/wiki/Kullback%E2%80%93Leibler_divergence"""
|
166 |
current_answer = market_row.currentAnswer # "yes", "no"
|
167 |
-
|
168 |
-
|
169 |
if current_answer == "no":
|
170 |
-
|
171 |
|
172 |
# we have only one sample, the final probability based on tokens
|
173 |
-
return kl_divergence(
|
174 |
|
175 |
|
176 |
def compute_tokens_prob(token_amounts: list) -> list:
|
|
|
164 |
"""Function to compute the divergence based on the formula
|
165 |
Formula in https://en.wikipedia.org/wiki/Kullback%E2%80%93Leibler_divergence"""
|
166 |
current_answer = market_row.currentAnswer # "yes", "no"
|
167 |
+
approx_prob = market_row.first_outcome_prob
|
168 |
+
true_prob = 0.99 # for yes outcome (99% is the max we can specify to avoid nan)
|
169 |
if current_answer == "no":
|
170 |
+
true_prob = 0.01 # = 0.1% for yes outcome and 99% for no
|
171 |
|
172 |
# we have only one sample, the final probability based on tokens
|
173 |
+
return kl_divergence(true_prob, approx_prob)
|
174 |
|
175 |
|
176 |
def compute_tokens_prob(token_amounts: list) -> list:
|
scripts/metrics.py
CHANGED
@@ -76,6 +76,28 @@ def compute_trader_metrics_by_market_creator(
|
|
76 |
return metrics
|
77 |
|
78 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
def merge_trader_metrics(
|
80 |
trader: str, weekly_data: pd.DataFrame, week: str
|
81 |
) -> pd.DataFrame:
|
@@ -143,6 +165,47 @@ def merge_trader_metrics_by_type(
|
|
143 |
return result
|
144 |
|
145 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
146 |
def compute_weekly_metrics_by_market_creator(
|
147 |
trader_agents_data: pd.DataFrame,
|
148 |
) -> pd.DataFrame:
|
@@ -179,3 +242,22 @@ def compute_weekly_metrics_by_trader_type(
|
|
179 |
contents.append(merge_trader_metrics_by_type(trader, weekly_data, week))
|
180 |
print("End computing all weekly metrics by trader types")
|
181 |
return pd.concat(contents, ignore_index=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
return metrics
|
77 |
|
78 |
|
79 |
+
def compute_winning_metric_per_trader_per_market_creator(
|
80 |
+
trader_address: str, week_traders_data: pd.DataFrame, market_creator: str = "all"
|
81 |
+
) -> float:
|
82 |
+
assert "market_creator" in week_traders_data.columns
|
83 |
+
filtered_traders_data = week_traders_data.loc[
|
84 |
+
week_traders_data["trader_address"] == trader_address
|
85 |
+
]
|
86 |
+
if market_creator != "all": # compute only for the specific market creator
|
87 |
+
filtered_traders_data = filtered_traders_data.loc[
|
88 |
+
filtered_traders_data["market_creator"] == market_creator
|
89 |
+
]
|
90 |
+
if len(filtered_traders_data) == 0:
|
91 |
+
tqdm.write(f"No data. Skipping market creator {market_creator}")
|
92 |
+
return None # No Data
|
93 |
+
winning_perc = (
|
94 |
+
filtered_traders_data["winning_trade"].sum()
|
95 |
+
/ filtered_traders_data["winning_trade"].count()
|
96 |
+
* 100.0
|
97 |
+
)
|
98 |
+
return winning_perc
|
99 |
+
|
100 |
+
|
101 |
def merge_trader_metrics(
|
102 |
trader: str, weekly_data: pd.DataFrame, week: str
|
103 |
) -> pd.DataFrame:
|
|
|
165 |
return result
|
166 |
|
167 |
|
168 |
+
def merge_winning_metrics_by_trader(
|
169 |
+
trader: str, weekly_data: pd.DataFrame, week: str
|
170 |
+
) -> pd.DataFrame:
|
171 |
+
trader_metrics = []
|
172 |
+
# computation as specification 1 for all market creators
|
173 |
+
winning_metrics_all = {}
|
174 |
+
winning_metric_all = compute_winning_metric_per_trader_per_market_creator(
|
175 |
+
trader, weekly_data, market_creator="all"
|
176 |
+
)
|
177 |
+
winning_metrics_all["winning_perc"] = winning_metric_all
|
178 |
+
winning_metrics_all["month_year_week"] = week
|
179 |
+
winning_metrics_all["market_creator"] = "all"
|
180 |
+
trader_metrics.append(winning_metrics_all)
|
181 |
+
|
182 |
+
# computation as specification 1 for quickstart markets
|
183 |
+
winning_metrics_qs = {}
|
184 |
+
winning_metric = compute_winning_metric_per_trader_per_market_creator(
|
185 |
+
trader, weekly_data, market_creator="quickstart"
|
186 |
+
)
|
187 |
+
if winning_metric:
|
188 |
+
winning_metrics_qs["winning_perc"] = winning_metric
|
189 |
+
winning_metrics_qs["month_year_week"] = week
|
190 |
+
winning_metrics_qs["market_creator"] = "quickstart"
|
191 |
+
trader_metrics.append(winning_metrics_qs)
|
192 |
+
|
193 |
+
# computation as specification 1 for pearl markets
|
194 |
+
winning_metrics_pearl = {}
|
195 |
+
winning_metric = compute_winning_metric_per_trader_per_market_creator(
|
196 |
+
trader, weekly_data, market_creator="pearl"
|
197 |
+
)
|
198 |
+
if winning_metric:
|
199 |
+
winning_metrics_pearl["winning_perc"] = winning_metric
|
200 |
+
winning_metrics_pearl["month_year_week"] = week
|
201 |
+
winning_metrics_pearl["market_creator"] = "pearl"
|
202 |
+
trader_metrics.append(winning_metrics_pearl)
|
203 |
+
|
204 |
+
result = pd.DataFrame.from_dict(trader_metrics, orient="columns")
|
205 |
+
# tqdm.write(f"Total length of all winning metrics for this week = {len(result)}")
|
206 |
+
return result
|
207 |
+
|
208 |
+
|
209 |
def compute_weekly_metrics_by_market_creator(
|
210 |
trader_agents_data: pd.DataFrame,
|
211 |
) -> pd.DataFrame:
|
|
|
242 |
contents.append(merge_trader_metrics_by_type(trader, weekly_data, week))
|
243 |
print("End computing all weekly metrics by trader types")
|
244 |
return pd.concat(contents, ignore_index=True)
|
245 |
+
|
246 |
+
|
247 |
+
def compute_winning_metrics_by_trader(
|
248 |
+
trader_agents_data: pd.DataFrame,
|
249 |
+
) -> pd.DataFrame:
|
250 |
+
"""Function to compute the winning metrics at the trader level per week and with different market creators"""
|
251 |
+
contents = []
|
252 |
+
all_weeks = list(trader_agents_data.month_year_week.unique())
|
253 |
+
for week in all_weeks:
|
254 |
+
weekly_data = trader_agents_data.loc[
|
255 |
+
trader_agents_data["month_year_week"] == week
|
256 |
+
]
|
257 |
+
print(f"Computing weekly metrics for week ={week} by trader type")
|
258 |
+
# traverse each trader agent
|
259 |
+
traders = list(weekly_data.trader_address.unique())
|
260 |
+
for trader in tqdm(traders, desc=f"Trader' metrics", unit="metrics"):
|
261 |
+
contents.append(merge_winning_metrics_by_trader(trader, weekly_data, week))
|
262 |
+
print("End computing all weekly winning metrics by trader")
|
263 |
+
return pd.concat(contents, ignore_index=True)
|
tabs/trader_plots.py
CHANGED
@@ -114,3 +114,25 @@ def plot_trader_metrics_by_trader_type(metric_name: str, traders_df: pd.DataFram
|
|
114 |
return gr.Plot(
|
115 |
value=fig,
|
116 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
return gr.Plot(
|
115 |
value=fig,
|
116 |
)
|
117 |
+
|
118 |
+
|
119 |
+
def plot_winning_metric_per_trader(traders_winning_df: pd.DataFrame) -> gr.Plot:
|
120 |
+
fig = px.box(
|
121 |
+
traders_winning_df,
|
122 |
+
x="month_year_week",
|
123 |
+
y="winning_perc",
|
124 |
+
color="market_creator",
|
125 |
+
color_discrete_sequence=["purple", "goldenrod", "darkgreen"],
|
126 |
+
category_orders={"market_creator": ["pearl", "quickstart", "all"]},
|
127 |
+
)
|
128 |
+
fig.update_traces(boxmean=True)
|
129 |
+
fig.update_layout(
|
130 |
+
xaxis_title="Week",
|
131 |
+
yaxis_title="Weekly winning percentage %",
|
132 |
+
legend=dict(yanchor="top", y=0.5),
|
133 |
+
)
|
134 |
+
fig.update_xaxes(tickformat="%b %d\n%Y")
|
135 |
+
|
136 |
+
return gr.Plot(
|
137 |
+
value=fig,
|
138 |
+
)
|