Files
bet/pev_eda.ipynb
2024-09-05 21:04:26 +08:00

2031 lines
56 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"from datetime import datetime\n",
"from dao.Database import Database\n",
"from data_model import MysqlConfig, OddsJamOrder, OddsjamBet"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"config_file_path = 'config\\mysql_config.json'\n",
"mysql_config = MysqlConfig.parse_file(config_file_path)\n",
"dao = Database(mysql_config)\n",
"\n",
"# query\n",
"select_query = \"SELECT * FROM bet.oddsjam_order where bet_status in ('won', 'lost');\"\n",
"raw_data_list = dao.fetchall(query=select_query)\n",
"order_data_list = [OddsJamOrder(**data).model_dump() for data in raw_data_list]"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'id': 'edge:10012-40335-2024-08-31:1st_half_team_total:oud-heverlee_leuven_over_0_5:oud-heverlee_leuven_under_0_5',\n",
" 'bet_id': 'edge:10012-40335-2024-08-31:1st_half_team_total:oud-heverlee_leuven_over_0_5:oud-heverlee_leuven_under_0_5',\n",
" 'game_id': '10012-40335-2024-08-31',\n",
" 'away_bet_name': 'Oud-Heverlee Leuven Under 0.5',\n",
" 'home_bet_name': 'Oud-Heverlee Leuven Over 0.5',\n",
" 'away_no_vig_price': 102.85,\n",
" 'home_no_vig_price': -102.85,\n",
" 'away_price': -110.0,\n",
" 'home_price': -102.0,\n",
" 'away_sportsbooks': ['FanDuel', 'DraftKings'],\n",
" 'home_sportsbooks': ['Bovada'],\n",
" 'is_live': False,\n",
" 'in_game_status': None,\n",
" 'period': None,\n",
" 'clock': None,\n",
" 'last_play': None,\n",
" 'home_score': 0,\n",
" 'away_score': 0,\n",
" 'sport': 'Soccer',\n",
" 'league': 'Belgium - Jupiler Pro League',\n",
" 'market': '1st Half Team Total',\n",
" 'market_width': 22.0,\n",
" 'percentage': 0.41,\n",
" 'start_date': datetime.datetime(2024, 9, 1, 2, 45),\n",
" 'home_team': 'Oud-Heverlee Leuven',\n",
" 'away_team': 'Royal Standard de Liège',\n",
" 'timestamp': 1725109490.1882415,\n",
" 'away_deep_link_map': '{\"FanDuel\": {\"urls\": {\"ios\": {\"url\": \"https://sportsbook.fanduel.com/addToBetslip?marketId=42.441130559&selectionId=7044483\", \"adds_to_slip\": true}, \"android\": {\"url\": \"https://sportsbook.fanduel.com/addToBetslip?marketId=42.441130559&selectionId=7044483\", \"adds_to_slip\": true}, \"desktop\": {\"url\": \"https://sportsbook.fanduel.com/addToBetslip?marketId=42.441130559&selectionId=7044483\", \"adds_to_slip\": true}}, \"mobile\": \"https://sportsbook.fanduel.com/addToBetslip?marketId=42.441130559&selectionId=7044483\", \"desktop\": \"https://sportsbook.fanduel.com/addToBetslip?marketId=42.441130559&selectionId=7044483\"}, \"DraftKings\": {\"urls\": {\"ios\": {\"url\": \"dksb://sb/addbet/0OU76429572U50_3\", \"adds_to_slip\": true}, \"android\": {\"url\": \"dksb://sb/addbet/0OU76429572U50_3\", \"adds_to_slip\": true}, \"desktop\": {\"url\": \"https://sportsbook.draftkings.com/event/30960358?outcomes=0OU76429572U50_3\", \"adds_to_slip\": true}}, \"mobile\": \"dksb://sb/addbet/0OU76429572U50_3\", \"desktop\": \"https://sportsbook.draftkings.com/event/30960358?outcomes=0OU76429572U50_3\"}}',\n",
" 'home_deep_link_map': '{}',\n",
" 'status': 'unplayed',\n",
" 'away_edge_percent': None,\n",
" 'bet_placed': False,\n",
" 'same_market_bet_placed': False,\n",
" 'same_game_bet_placed': False,\n",
" 'away_rec_size': None,\n",
" 'rec_size': 1,\n",
" 'home_edge_percent': 0.41,\n",
" 'order_status': 0,\n",
" 'amount': None,\n",
" 'create_time': '20240831211007',\n",
" 'sportsbook_orderid': None,\n",
" 'home_or_away': 'home',\n",
" 'start_timestamp': 1725129900000,\n",
" 'selected_sportsbook': 'Bovada',\n",
" 'bet_status': 'won'}"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"order_data_list[1]"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [],
"source": [
"db_df = pd.DataFrame(order_data_list)"
]
},
{
"cell_type": "code",
"execution_count": 176,
"metadata": {},
"outputs": [],
"source": [
"def get_benefit(row):\n",
" home_or_away = row['home_or_away']\n",
" price = row[f'{home_or_away}_price'] / 100\n",
" if row['outcome'] == -1:\n",
" return -1\n",
" if price >= 0:\n",
" return price \n",
" else:\n",
" return 1 / abs(price) \n",
" \n",
"db_df['outcome'] = db_df['bet_status'].apply(lambda x: 1 if x == 'won' else -1)\n",
"db_df['benefit'] = db_df.apply(get_benefit, axis=1)\n",
"db_df['date'] = db_df['start_timestamp'].apply(lambda x: datetime.fromtimestamp(x // 1000).strftime(\"%Y-%m-%d\"))"
]
},
{
"cell_type": "code",
"execution_count": 153,
"metadata": {},
"outputs": [],
"source": [
"def get_odds(row):\n",
" home_or_away = row['home_or_away']\n",
" price = row[f'{home_or_away}_price'] / 100\n",
"\n",
" if price >= 0:\n",
" return price\n",
" else:\n",
" return 1 / abs(price) "
]
},
{
"cell_type": "code",
"execution_count": 154,
"metadata": {},
"outputs": [],
"source": [
"db_df['odds2'] = db_df.apply(get_odds, axis=1)"
]
},
{
"cell_type": "code",
"execution_count": 144,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3.4551825216755248"
]
},
"execution_count": 144,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"db_df['odds2'].mean()"
]
},
{
"cell_type": "code",
"execution_count": 133,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"bet_status\n",
"lost 13439\n",
"won 5902\n",
"dtype: int64"
]
},
"execution_count": 133,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"db_df.groupby('bet_status').size()"
]
},
{
"cell_type": "code",
"execution_count": 130,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3.4551825216755248"
]
},
"execution_count": 130,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"db_df[db_df['bet_status'].isin(['won', 'lost'])]['benefit'].mean()"
]
},
{
"cell_type": "code",
"execution_count": 149,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"-1477.1127282023094"
]
},
"execution_count": 149,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"db_df[['home_price', 'away_price', 'home_or_away', 'bet_status', 'benefit']]['benefit']"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 166,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"count 1780.000000\n",
"mean 1.165759\n",
"std 0.338662\n",
"min 0.359712\n",
"25% 0.909091\n",
"50% 1.080000\n",
"75% 1.360000\n",
"max 4.000000\n",
"Name: odds2, dtype: float64"
]
},
"execution_count": 166,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"db_df[(db_df['market_width'] <= 25) & (db_df['market_width'] >= 20)]['odds2'].describe()"
]
},
{
"cell_type": "code",
"execution_count": 168,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"bet_status\n",
"lost 932\n",
"won 848\n",
"dtype: int64"
]
},
"execution_count": 168,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"db_df[(db_df['market_width'] <= 25) & (db_df['market_width'] >= 20)].groupby(['bet_status']).size()"
]
},
{
"cell_type": "code",
"execution_count": 171,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.4764044943820225"
]
},
"execution_count": 171,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"848 / (848+932)"
]
},
{
"cell_type": "code",
"execution_count": 170,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.0318921348314607"
]
},
"execution_count": 170,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"848 / (848+932) * (1.166 + 1)"
]
},
{
"cell_type": "code",
"execution_count": 156,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"count 5902.000000\n",
"mean 2.026751\n",
"std 1.825651\n",
"min 0.166667\n",
"25% 1.020000\n",
"50% 1.430000\n",
"75% 2.200000\n",
"max 25.000000\n",
"Name: odds2, dtype: float64"
]
},
"execution_count": 156,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"db_df[db_df['bet_status'] == 'won']['odds2'].describe()"
]
},
{
"cell_type": "code",
"execution_count": 157,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"count 13439.000000\n",
"mean 4.082506\n",
"std 3.955954\n",
"min 0.235294\n",
"25% 1.500000\n",
"50% 2.700000\n",
"75% 5.400000\n",
"max 35.000000\n",
"Name: odds2, dtype: float64"
]
},
"execution_count": 157,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"db_df[db_df['bet_status'] == 'lost']['odds2'].describe()"
]
},
{
"cell_type": "code",
"execution_count": 116,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"count 19341.000000\n",
"mean 392.987177\n",
"std 1713.715890\n",
"min 5.000000\n",
"25% 33.000000\n",
"50% 75.000000\n",
"75% 244.000000\n",
"max 49049.000000\n",
"Name: market_width, dtype: float64"
]
},
"execution_count": 116,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"db_df['market_width'].describe()"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {},
"outputs": [],
"source": [
"lost_df = db_df[db_df['outcome'] == -1]"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"count 13439.000000\n",
"mean 517.244661\n",
"std 2026.572578\n",
"min 5.000000\n",
"25% 40.000000\n",
"50% 105.000000\n",
"75% 348.000000\n",
"max 49049.000000\n",
"Name: market_width, dtype: float64"
]
},
"execution_count": 49,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lost_df['market_width'].describe()"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"raw_df = pd.read_excel('PEV 3.11-10.26.xlsx', sheet_name='原始数据')"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>away_team</th>\n",
" <th>best_price_away_name</th>\n",
" <th>best_price_away_odd</th>\n",
" <th>best_price_away_odd_books_new</th>\n",
" <th>best_price_home_name</th>\n",
" <th>best_price_home_odd</th>\n",
" <th>best_price_home_odd_books_new</th>\n",
" <th>home_team</th>\n",
" <th>league</th>\n",
" <th>market</th>\n",
" <th>sport</th>\n",
" <th>date</th>\n",
" <th>weighted_price_away_odd</th>\n",
" <th>weighted_price_home_odd</th>\n",
" <th>handicap to go</th>\n",
" <th>outcome</th>\n",
" <th>odds US</th>\n",
" <th>odds EU</th>\n",
" <th>benefit</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>FC Augsburg</td>\n",
" <td>Under 4.5</td>\n",
" <td>-150</td>\n",
" <td>OddsJam,William Hill,Caesars</td>\n",
" <td>Over 4.5</td>\n",
" <td>162</td>\n",
" <td>FanDuel</td>\n",
" <td>FC Bayern Munich</td>\n",
" <td>Germany - Bundesliga</td>\n",
" <td>Total Goals</td>\n",
" <td>soccer</td>\n",
" <td>2023-03-11</td>\n",
" <td>-141.153</td>\n",
" <td>142.032</td>\n",
" <td>Over 4.5</td>\n",
" <td>1.0</td>\n",
" <td>162</td>\n",
" <td>1.620000</td>\n",
" <td>1.620000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>FC Augsburg</td>\n",
" <td>FC Bayern Munich Under 3.5</td>\n",
" <td>-137</td>\n",
" <td>OddsJam</td>\n",
" <td>FC Bayern Munich Over 3.5</td>\n",
" <td>146</td>\n",
" <td>FanDuel</td>\n",
" <td>FC Bayern Munich</td>\n",
" <td>Germany - Bundesliga</td>\n",
" <td>Team Total</td>\n",
" <td>soccer</td>\n",
" <td>2023-03-11</td>\n",
" <td>-126.848</td>\n",
" <td>127.536</td>\n",
" <td>FC Bayern Munich Over 3.5</td>\n",
" <td>1.0</td>\n",
" <td>146</td>\n",
" <td>1.460000</td>\n",
" <td>1.460000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>FC Augsburg</td>\n",
" <td>FC Bayern Munich Under 1.5</td>\n",
" <td>-135</td>\n",
" <td>DraftKings,10bet,DraftKings (Tennessee)</td>\n",
" <td>FC Bayern Munich Over 1.5</td>\n",
" <td>128</td>\n",
" <td>FanDuel</td>\n",
" <td>FC Bayern Munich</td>\n",
" <td>Germany - Bundesliga</td>\n",
" <td>1st Half Team Total</td>\n",
" <td>soccer</td>\n",
" <td>2023-03-11</td>\n",
" <td>-123.407</td>\n",
" <td>123.898</td>\n",
" <td>FC Bayern Munich Over 1.5</td>\n",
" <td>1.0</td>\n",
" <td>128</td>\n",
" <td>1.280000</td>\n",
" <td>1.280000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>Liverpool</td>\n",
" <td>Bournemouth Under 0.5</td>\n",
" <td>132</td>\n",
" <td>FanDuel</td>\n",
" <td>Bournemouth Over 0.5</td>\n",
" <td>-137</td>\n",
" <td>Barstool</td>\n",
" <td>Bournemouth</td>\n",
" <td>England - Premier League</td>\n",
" <td>Team Total</td>\n",
" <td>soccer</td>\n",
" <td>2023-03-11</td>\n",
" <td>141.875</td>\n",
" <td>-141.519</td>\n",
" <td>Bournemouth Over 0.5</td>\n",
" <td>1.0</td>\n",
" <td>-137</td>\n",
" <td>0.729927</td>\n",
" <td>0.729927</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>FC Augsburg</td>\n",
" <td>Under 3.5</td>\n",
" <td>141</td>\n",
" <td>OddsJam</td>\n",
" <td>Over 3.5</td>\n",
" <td>-138</td>\n",
" <td>FanDuel</td>\n",
" <td>FC Bayern Munich</td>\n",
" <td>Germany - Bundesliga</td>\n",
" <td>Total Goals</td>\n",
" <td>soccer</td>\n",
" <td>2023-03-11</td>\n",
" <td>147.467</td>\n",
" <td>-146.976</td>\n",
" <td>Over 3.5</td>\n",
" <td>1.0</td>\n",
" <td>-138</td>\n",
" <td>0.724638</td>\n",
" <td>0.724638</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>80358</th>\n",
" <td>New Orleans Pelicans</td>\n",
" <td>Memphis Grizzlies +1.5</td>\n",
" <td>-143</td>\n",
" <td>TonyBet</td>\n",
" <td>New Orleans Pelicans -1.5</td>\n",
" <td>135</td>\n",
" <td>BetMGM,partypoker,Borgata</td>\n",
" <td>Memphis Grizzlies</td>\n",
" <td>NBA</td>\n",
" <td>1st Half Point Spread</td>\n",
" <td>Basketball</td>\n",
" <td>2023-10-26</td>\n",
" <td>-133.490</td>\n",
" <td>133.546</td>\n",
" <td>New Orleans Pelicans -1.5</td>\n",
" <td>1.0</td>\n",
" <td>135</td>\n",
" <td>1.350000</td>\n",
" <td>1.350000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>80360</th>\n",
" <td>Dallas Mavericks</td>\n",
" <td>San Antonio Spurs -0.5</td>\n",
" <td>148</td>\n",
" <td>FanDuel</td>\n",
" <td>Dallas Mavericks +0.5</td>\n",
" <td>-155</td>\n",
" <td>Pinny,Pinnacle</td>\n",
" <td>San Antonio Spurs</td>\n",
" <td>NBA</td>\n",
" <td>1st Half Point Spread</td>\n",
" <td>Basketball</td>\n",
" <td>2023-10-26</td>\n",
" <td>146.604</td>\n",
" <td>-146.127</td>\n",
" <td>San Antonio Spurs -0.5</td>\n",
" <td>1.0</td>\n",
" <td>148</td>\n",
" <td>1.480000</td>\n",
" <td>1.480000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>80361</th>\n",
" <td>Dallas Mavericks</td>\n",
" <td>San Antonio Spurs +0.5</td>\n",
" <td>128</td>\n",
" <td>FanDuel</td>\n",
" <td>Dallas Mavericks -0.5</td>\n",
" <td>-132</td>\n",
" <td>Pinny,Pinnacle</td>\n",
" <td>San Antonio Spurs</td>\n",
" <td>NBA</td>\n",
" <td>1st Half Point Spread</td>\n",
" <td>Basketball</td>\n",
" <td>2023-10-26</td>\n",
" <td>126.875</td>\n",
" <td>-126.419</td>\n",
" <td>San Antonio Spurs +0.5</td>\n",
" <td>1.0</td>\n",
" <td>128</td>\n",
" <td>1.280000</td>\n",
" <td>1.280000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>80363</th>\n",
" <td>Portland Trail Blazers</td>\n",
" <td>Los Angeles Clippers Under 60.5</td>\n",
" <td>-116</td>\n",
" <td>Pinny,Pinnacle</td>\n",
" <td>Los Angeles Clippers Over 60.5</td>\n",
" <td>110</td>\n",
" <td>partypoker,BetMGM,Borgata</td>\n",
" <td>Los Angeles Clippers</td>\n",
" <td>NBA</td>\n",
" <td>1st Half Team Total</td>\n",
" <td>Basketball</td>\n",
" <td>2023-10-26</td>\n",
" <td>-106.549</td>\n",
" <td>106.565</td>\n",
" <td>Los Angeles Clippers Over 60.5</td>\n",
" <td>1.0</td>\n",
" <td>110</td>\n",
" <td>1.100000</td>\n",
" <td>1.100000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>80365</th>\n",
" <td>Portland Trail Blazers</td>\n",
" <td>Los Angeles Clippers -3.5</td>\n",
" <td>104</td>\n",
" <td>Unibet,BetRivers,betPARX</td>\n",
" <td>Portland Trail Blazers +3.5</td>\n",
" <td>-110</td>\n",
" <td>BetAnySports,LowVig,BetOnline,SuperBook</td>\n",
" <td>Los Angeles Clippers</td>\n",
" <td>NBA</td>\n",
" <td>1st Quarter Point Spread</td>\n",
" <td>Basketball</td>\n",
" <td>2023-10-26</td>\n",
" <td>103.013</td>\n",
" <td>-102.757</td>\n",
" <td>Los Angeles Clippers -3.5</td>\n",
" <td>1.0</td>\n",
" <td>104</td>\n",
" <td>1.040000</td>\n",
" <td>1.040000</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>37469 rows × 19 columns</p>\n",
"</div>"
],
"text/plain": [
" away_team best_price_away_name \\\n",
"0 FC Augsburg Under 4.5 \n",
"1 FC Augsburg FC Bayern Munich Under 3.5 \n",
"2 FC Augsburg FC Bayern Munich Under 1.5 \n",
"6 Liverpool Bournemouth Under 0.5 \n",
"8 FC Augsburg Under 3.5 \n",
"... ... ... \n",
"80358 New Orleans Pelicans Memphis Grizzlies +1.5 \n",
"80360 Dallas Mavericks San Antonio Spurs -0.5 \n",
"80361 Dallas Mavericks San Antonio Spurs +0.5 \n",
"80363 Portland Trail Blazers Los Angeles Clippers Under 60.5 \n",
"80365 Portland Trail Blazers Los Angeles Clippers -3.5 \n",
"\n",
" best_price_away_odd best_price_away_odd_books_new \\\n",
"0 -150 OddsJam,William Hill,Caesars \n",
"1 -137 OddsJam \n",
"2 -135 DraftKings,10bet,DraftKings (Tennessee) \n",
"6 132 FanDuel \n",
"8 141 OddsJam \n",
"... ... ... \n",
"80358 -143 TonyBet \n",
"80360 148 FanDuel \n",
"80361 128 FanDuel \n",
"80363 -116 Pinny,Pinnacle \n",
"80365 104 Unibet,BetRivers,betPARX \n",
"\n",
" best_price_home_name best_price_home_odd \\\n",
"0 Over 4.5 162 \n",
"1 FC Bayern Munich Over 3.5 146 \n",
"2 FC Bayern Munich Over 1.5 128 \n",
"6 Bournemouth Over 0.5 -137 \n",
"8 Over 3.5 -138 \n",
"... ... ... \n",
"80358 New Orleans Pelicans -1.5 135 \n",
"80360 Dallas Mavericks +0.5 -155 \n",
"80361 Dallas Mavericks -0.5 -132 \n",
"80363 Los Angeles Clippers Over 60.5 110 \n",
"80365 Portland Trail Blazers +3.5 -110 \n",
"\n",
" best_price_home_odd_books_new home_team \\\n",
"0 FanDuel FC Bayern Munich \n",
"1 FanDuel FC Bayern Munich \n",
"2 FanDuel FC Bayern Munich \n",
"6 Barstool Bournemouth \n",
"8 FanDuel FC Bayern Munich \n",
"... ... ... \n",
"80358 BetMGM,partypoker,Borgata Memphis Grizzlies \n",
"80360 Pinny,Pinnacle San Antonio Spurs \n",
"80361 Pinny,Pinnacle San Antonio Spurs \n",
"80363 partypoker,BetMGM,Borgata Los Angeles Clippers \n",
"80365 BetAnySports,LowVig,BetOnline,SuperBook Los Angeles Clippers \n",
"\n",
" league market sport \\\n",
"0 Germany - Bundesliga Total Goals soccer \n",
"1 Germany - Bundesliga Team Total soccer \n",
"2 Germany - Bundesliga 1st Half Team Total soccer \n",
"6 England - Premier League Team Total soccer \n",
"8 Germany - Bundesliga Total Goals soccer \n",
"... ... ... ... \n",
"80358 NBA 1st Half Point Spread Basketball \n",
"80360 NBA 1st Half Point Spread Basketball \n",
"80361 NBA 1st Half Point Spread Basketball \n",
"80363 NBA 1st Half Team Total Basketball \n",
"80365 NBA 1st Quarter Point Spread Basketball \n",
"\n",
" date weighted_price_away_odd weighted_price_home_odd \\\n",
"0 2023-03-11 -141.153 142.032 \n",
"1 2023-03-11 -126.848 127.536 \n",
"2 2023-03-11 -123.407 123.898 \n",
"6 2023-03-11 141.875 -141.519 \n",
"8 2023-03-11 147.467 -146.976 \n",
"... ... ... ... \n",
"80358 2023-10-26 -133.490 133.546 \n",
"80360 2023-10-26 146.604 -146.127 \n",
"80361 2023-10-26 126.875 -126.419 \n",
"80363 2023-10-26 -106.549 106.565 \n",
"80365 2023-10-26 103.013 -102.757 \n",
"\n",
" handicap to go outcome odds US odds EU benefit \n",
"0 Over 4.5 1.0 162 1.620000 1.620000 \n",
"1 FC Bayern Munich Over 3.5 1.0 146 1.460000 1.460000 \n",
"2 FC Bayern Munich Over 1.5 1.0 128 1.280000 1.280000 \n",
"6 Bournemouth Over 0.5 1.0 -137 0.729927 0.729927 \n",
"8 Over 3.5 1.0 -138 0.724638 0.724638 \n",
"... ... ... ... ... ... \n",
"80358 New Orleans Pelicans -1.5 1.0 135 1.350000 1.350000 \n",
"80360 San Antonio Spurs -0.5 1.0 148 1.480000 1.480000 \n",
"80361 San Antonio Spurs +0.5 1.0 128 1.280000 1.280000 \n",
"80363 Los Angeles Clippers Over 60.5 1.0 110 1.100000 1.100000 \n",
"80365 Los Angeles Clippers -3.5 1.0 104 1.040000 1.040000 \n",
"\n",
"[37469 rows x 19 columns]"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"raw_df[raw_df['outcome'] == 1]"
]
},
{
"cell_type": "code",
"execution_count": 93,
"metadata": {},
"outputs": [],
"source": [
"data_df = raw_df.copy()\n",
"data_df['investment'] = 1"
]
},
{
"cell_type": "code",
"execution_count": 179,
"metadata": {},
"outputs": [],
"source": [
"\n",
"data_df = db_df.copy()\n",
"data_df = data_df[data_df['market_width'] <= 25]\n",
"data_df = data_df[data_df['market_width'] >= 20]\n",
"# data_df = data_df[data_df['selected_sportsbook'] == '1XBet']\n",
"data_df['investment'] = 1"
]
},
{
"cell_type": "code",
"execution_count": 180,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"年化夏普率: 0.8002309699976565\n",
"ROI: 0.00683522830064485\n"
]
}
],
"source": [
"def clac_closing_balance(day_benefit_list, pre_balance=1000, pre_benefit=0):\n",
" closing_balance_list = []\n",
" for i, benefit in enumerate(day_benefit_list):\n",
" closing_balance = pre_balance + pre_benefit / 3 + benefit * 2 / 3\n",
" closing_balance_list.append(closing_balance)\n",
" pre_balance = closing_balance\n",
" pre_benefit = benefit\n",
" return closing_balance_list\n",
"\n",
"def calc_in_transit_funds_ratio(daily_investment_list, closing_balance_list, start_closing_balance=1000):\n",
" assert len(daily_investment_list) == len(closing_balance_list)\n",
" ratio_list = []\n",
" for i, daily_investment in enumerate(daily_investment_list):\n",
" if i == 0:\n",
" ratio = daily_investment / start_closing_balance\n",
" else:\n",
" ratio = daily_investment / closing_balance_list[i-1]\n",
" ratio_list.append(ratio)\n",
" return ratio_list\n",
"\n",
"\n",
"init_balance = 1000\n",
"res_df = data_df.groupby('date').agg({'investment':'sum', 'benefit':'sum'}).rename(columns={'investment':'当日投入', 'benefit':'日收益'}).reset_index()\n",
"res_df['日收益率'] = res_df['日收益'] / res_df['当日投入']\n",
"res_df['累计收益'] = res_df['日收益'].cumsum()\n",
"res_df['累计投入'] = res_df['当日投入'].cumsum()\n",
"res_df['累计收益率'] = res_df['累计收益'] / res_df['累计投入']\n",
"\n",
"day_benefit_list = res_df['日收益'].tolist()\n",
"closing_balance_list = clac_closing_balance(day_benefit_list=day_benefit_list, pre_balance=init_balance)\n",
"res_df['日末余额(1.6天结算)'] = closing_balance_list\n",
"\n",
"daily_investment_list = res_df['当日投入'].tolist()\n",
"res_df['在途资金比例'] = calc_in_transit_funds_ratio(daily_investment_list=daily_investment_list, closing_balance_list=closing_balance_list, start_closing_balance=init_balance)\n",
"annualized_sharpe_ratio = res_df['日收益'].sum() / init_balance / res_df['日收益率'].std() * ((365 / len(res_df))**0.5)\n",
"print(f'年化夏普率: {annualized_sharpe_ratio}')\n",
"roi = res_df['日收益'].sum() / res_df['当日投入'].sum()\n",
"print(f'ROI: {roi}')"
]
},
{
"cell_type": "code",
"execution_count": 181,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.plotly.v1+json": {
"config": {
"plotlyServerURL": "https://plot.ly"
},
"data": [
{
"mode": "lines",
"name": "日末余额",
"type": "scatter",
"x": [
"2024-08-26T00:00:00",
"2024-08-27T00:00:00",
"2024-08-28T00:00:00",
"2024-08-29T00:00:00",
"2024-08-30T00:00:00",
"2024-08-31T00:00:00",
"2024-09-01T00:00:00"
],
"y": [
1002.6656885456886,
1029.320085562455,
1031.6353596927408,
1014.877157613626,
1004.9262841780602,
1010.5006139053265,
1012.8869095027875
],
"yaxis": "y"
},
{
"mode": "lines",
"name": "累计收益率",
"type": "scatter",
"x": [
"2024-08-26T00:00:00",
"2024-08-27T00:00:00",
"2024-08-28T00:00:00",
"2024-08-29T00:00:00",
"2024-08-30T00:00:00",
"2024-08-31T00:00:00",
"2024-09-01T00:00:00"
],
"y": [
0.17384925297968776,
0.18095199109662177,
0.05703148399117068,
0.013933178120379116,
0.0027913825488691288,
0.01187018704065157,
0.00683522830064485
],
"yaxis": "y2"
}
],
"layout": {
"template": {
"data": {
"bar": [
{
"error_x": {
"color": "#2a3f5f"
},
"error_y": {
"color": "#2a3f5f"
},
"marker": {
"line": {
"color": "#E5ECF6",
"width": 0.5
},
"pattern": {
"fillmode": "overlay",
"size": 10,
"solidity": 0.2
}
},
"type": "bar"
}
],
"barpolar": [
{
"marker": {
"line": {
"color": "#E5ECF6",
"width": 0.5
},
"pattern": {
"fillmode": "overlay",
"size": 10,
"solidity": 0.2
}
},
"type": "barpolar"
}
],
"carpet": [
{
"aaxis": {
"endlinecolor": "#2a3f5f",
"gridcolor": "white",
"linecolor": "white",
"minorgridcolor": "white",
"startlinecolor": "#2a3f5f"
},
"baxis": {
"endlinecolor": "#2a3f5f",
"gridcolor": "white",
"linecolor": "white",
"minorgridcolor": "white",
"startlinecolor": "#2a3f5f"
},
"type": "carpet"
}
],
"choropleth": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"type": "choropleth"
}
],
"contour": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "contour"
}
],
"contourcarpet": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"type": "contourcarpet"
}
],
"heatmap": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "heatmap"
}
],
"heatmapgl": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "heatmapgl"
}
],
"histogram": [
{
"marker": {
"pattern": {
"fillmode": "overlay",
"size": 10,
"solidity": 0.2
}
},
"type": "histogram"
}
],
"histogram2d": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "histogram2d"
}
],
"histogram2dcontour": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "histogram2dcontour"
}
],
"mesh3d": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"type": "mesh3d"
}
],
"parcoords": [
{
"line": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "parcoords"
}
],
"pie": [
{
"automargin": true,
"type": "pie"
}
],
"scatter": [
{
"fillpattern": {
"fillmode": "overlay",
"size": 10,
"solidity": 0.2
},
"type": "scatter"
}
],
"scatter3d": [
{
"line": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scatter3d"
}
],
"scattercarpet": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scattercarpet"
}
],
"scattergeo": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scattergeo"
}
],
"scattergl": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scattergl"
}
],
"scattermapbox": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scattermapbox"
}
],
"scatterpolar": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scatterpolar"
}
],
"scatterpolargl": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scatterpolargl"
}
],
"scatterternary": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scatterternary"
}
],
"surface": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "surface"
}
],
"table": [
{
"cells": {
"fill": {
"color": "#EBF0F8"
},
"line": {
"color": "white"
}
},
"header": {
"fill": {
"color": "#C8D4E3"
},
"line": {
"color": "white"
}
},
"type": "table"
}
]
},
"layout": {
"annotationdefaults": {
"arrowcolor": "#2a3f5f",
"arrowhead": 0,
"arrowwidth": 1
},
"autotypenumbers": "strict",
"coloraxis": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"colorscale": {
"diverging": [
[
0,
"#8e0152"
],
[
0.1,
"#c51b7d"
],
[
0.2,
"#de77ae"
],
[
0.3,
"#f1b6da"
],
[
0.4,
"#fde0ef"
],
[
0.5,
"#f7f7f7"
],
[
0.6,
"#e6f5d0"
],
[
0.7,
"#b8e186"
],
[
0.8,
"#7fbc41"
],
[
0.9,
"#4d9221"
],
[
1,
"#276419"
]
],
"sequential": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"sequentialminus": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
]
},
"colorway": [
"#636efa",
"#EF553B",
"#00cc96",
"#ab63fa",
"#FFA15A",
"#19d3f3",
"#FF6692",
"#B6E880",
"#FF97FF",
"#FECB52"
],
"font": {
"color": "#2a3f5f"
},
"geo": {
"bgcolor": "white",
"lakecolor": "white",
"landcolor": "#E5ECF6",
"showlakes": true,
"showland": true,
"subunitcolor": "white"
},
"hoverlabel": {
"align": "left"
},
"hovermode": "closest",
"mapbox": {
"style": "light"
},
"paper_bgcolor": "white",
"plot_bgcolor": "#E5ECF6",
"polar": {
"angularaxis": {
"gridcolor": "white",
"linecolor": "white",
"ticks": ""
},
"bgcolor": "#E5ECF6",
"radialaxis": {
"gridcolor": "white",
"linecolor": "white",
"ticks": ""
}
},
"scene": {
"xaxis": {
"backgroundcolor": "#E5ECF6",
"gridcolor": "white",
"gridwidth": 2,
"linecolor": "white",
"showbackground": true,
"ticks": "",
"zerolinecolor": "white"
},
"yaxis": {
"backgroundcolor": "#E5ECF6",
"gridcolor": "white",
"gridwidth": 2,
"linecolor": "white",
"showbackground": true,
"ticks": "",
"zerolinecolor": "white"
},
"zaxis": {
"backgroundcolor": "#E5ECF6",
"gridcolor": "white",
"gridwidth": 2,
"linecolor": "white",
"showbackground": true,
"ticks": "",
"zerolinecolor": "white"
}
},
"shapedefaults": {
"line": {
"color": "#2a3f5f"
}
},
"ternary": {
"aaxis": {
"gridcolor": "white",
"linecolor": "white",
"ticks": ""
},
"baxis": {
"gridcolor": "white",
"linecolor": "white",
"ticks": ""
},
"bgcolor": "#E5ECF6",
"caxis": {
"gridcolor": "white",
"linecolor": "white",
"ticks": ""
}
},
"title": {
"x": 0.05
},
"xaxis": {
"automargin": true,
"gridcolor": "white",
"linecolor": "white",
"ticks": "",
"title": {
"standoff": 15
},
"zerolinecolor": "white",
"zerolinewidth": 2
},
"yaxis": {
"automargin": true,
"gridcolor": "white",
"linecolor": "white",
"ticks": "",
"title": {
"standoff": 15
},
"zerolinecolor": "white",
"zerolinewidth": 2
}
}
},
"title": {
"text": "日末余额(1.6天结算) 和 累计收益率 折线图"
},
"xaxis": {
"title": {
"text": "日期"
}
},
"yaxis": {
"title": {
"text": "金额"
}
},
"yaxis2": {
"overlaying": "y",
"side": "right",
"tickformat": ".1%",
"title": {
"text": "收益率"
}
}
}
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import pandas as pd\n",
"import plotly.graph_objects as go\n",
"\n",
"res_df['日期'] = pd.to_datetime(res_df['date'])\n",
"\n",
"fig = go.Figure()\n",
"\n",
"# 添加日末余额(1.6天结算)的折线图\n",
"fig.add_trace(go.Scatter(\n",
" x=res_df['日期'],\n",
" y=res_df['日末余额(1.6天结算)'],\n",
" mode='lines',\n",
" name='日末余额',\n",
" yaxis='y1'\n",
"))\n",
"\n",
"# 添加日收益率的折线图\n",
"# fig.add_trace(go.Scatter(\n",
"# x=res_df['日期'],\n",
"# y=res_df['日收益率'],\n",
"# mode='lines',\n",
"# name='日收益率',\n",
"# yaxis='y2'\n",
"# ))\n",
"\n",
"# 添加累计收益率的折线图\n",
"fig.add_trace(go.Scatter(\n",
" x=res_df['日期'],\n",
" y=res_df['累计收益率'],\n",
" mode='lines',\n",
" name='累计收益率',\n",
" yaxis='y2'\n",
"))\n",
"\n",
"# 添加在途资金比例的折线图\n",
"# fig.add_trace(go.Scatter(\n",
"# x=res_df['日期'],\n",
"# y=res_df['在途资金比例'],\n",
"# mode='lines',\n",
"# name='在途资金比例',\n",
"# yaxis='y2'\n",
"# ))\n",
"\n",
"# 设置布局添加第二个y轴\n",
"fig.update_layout(\n",
" title='日末余额(1.6天结算) 和 累计收益率 折线图',\n",
" xaxis=dict(title='日期'),\n",
" yaxis=dict(title='金额'),\n",
" yaxis2=dict(title='收益率', overlaying='y', side='right', tickformat='.1%')\n",
")\n",
"\n",
"\n",
"fig.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 基于market width 进行分层, 然后计算年华夏普率值, 进行资金配比"
]
},
{
"cell_type": "code",
"execution_count": 74,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>outcome</th>\n",
" <th>count</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>-1.0</td>\n",
" <td>39838</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>1.0</td>\n",
" <td>37469</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>0.0</td>\n",
" <td>2804</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>-0.5</td>\n",
" <td>164</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>0.5</td>\n",
" <td>91</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" outcome count\n",
"0 -1.0 39838\n",
"4 1.0 37469\n",
"2 0.0 2804\n",
"1 -0.5 164\n",
"3 0.5 91"
]
},
"execution_count": 74,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"raw_df.groupby('outcome').agg({'away_team': 'count'}).rename(columns={'away_team': 'count'}).reset_index().sort_values(by='count', ascending=False)"
]
},
{
"cell_type": "code",
"execution_count": 75,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.1811803969722776"
]
},
"execution_count": 75,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"raw_df['odds EU'].mean()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "base",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.9"
}
},
"nbformat": 4,
"nbformat_minor": 2
}