| Overall Statistics |
|
Total Trades
1388
Average Win
2.00%
Average Loss
-1.21%
Compounding Annual Return
8.829%
Drawdown
47.800%
Expectancy
0.269
Net Profit
587.312%
Sharpe Ratio
0.506
Probabilistic Sharpe Ratio
0.175%
Loss Rate
52%
Win Rate
48%
Profit-Loss Ratio
1.66
Alpha
0.072
Beta
-0.019
Annual Standard Deviation
0.139
Annual Variance
0.019
Information Ratio
0.073
Tracking Error
0.216
Treynor Ratio
-3.783
Total Fees
$14232.19
Estimated Strategy Capacity
$0
Lowest Capacity Asset
JUVE.QuantpediaSoccer 2S
|
# https://quantpedia.com/strategies/soccer-clubs-stocks-arbitrage/
#
# The investment universe consists of liquid soccer clubs’ stocks that are publicly traded.
# The investor then sells short stocks of clubs that play UEFA Championship matches (or other important matches)
# at the end of the business day before the match. Stocks are held for one day,
# and the portfolio of stocks is equally weighted (if there are multiple clubs with matches that day).
#
# QC Implementation:
#region imports
from AlgorithmImports import *
#endregion
class SoccerClubsStocksArbitrage(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2000, 1, 1)
self.SetCash(100000)
self.tickers = [
'FCPP', # Futebol Clube Do Porto
'SPSO', # Sporting Clube De Portugal
'SLBEN', # Benfica
'LAZI', # Lazio
'ASR', # AS Rome
'AJAX', # AJAX
'JUVE', # Juventus
'MANU', # Manchester United
'BVB', # Dortmund
'CCP', # Celtic
# 'BOLA' # Bali Bintang Sejahtera Tbk PT
]
self.match_dates = {}
for ticker in self.tickers:
security = self.AddData(QuantpediaSoccer, ticker, Resolution.Daily)
security.SetFeeModel(CustomFeeModel())
security.SetLeverage(5)
csv_string_file = self.Download('data.quantpedia.com/backtesting_data/equity/soccer/soccer_matches.csv')
lines = csv_string_file.split('\r\n')
for line in lines:
line_split = line.split(';')
date = datetime.strptime(line_split[0], "%d.%m.%Y").date()
self.match_dates[date] = []
for i in range(1, len(line_split)):
ticker = line_split[i]
self.match_dates[date].append(ticker)
def OnData(self, data):
self.Liquidate()
short = []
# Looking for todays date, because only daily closes are traded.
today = (self.Time - timedelta(days=1)).date()
if today in self.match_dates:
for ticker in self.tickers:
if ticker in self.match_dates[today] and ticker in data:
short.append(ticker)
for ticker in short:
self.SetHoldings(ticker, -1 / len(short))
# Quantpedia data.
# NOTE: IMPORTANT: Data order must be ascending (datewise)
class QuantpediaSoccer(PythonData):
def GetSource(self, config, date, isLiveMode):
return SubscriptionDataSource("data.quantpedia.com/backtesting_data/equity/soccer/{0}.csv".format(config.Symbol.Value), SubscriptionTransportMedium.RemoteFile, FileFormat.Csv)
def Reader(self, config, line, date, isLiveMode):
data = QuantpediaSoccer()
data.Symbol = config.Symbol
if not line[0].isdigit(): return None
split = line.split(';')
data.Time = datetime.strptime(split[0], "%d.%m.%Y") + timedelta(days=1)
data['price'] = float(split[1])
data.Value = float(split[1])
return data
# Custom fee model.
class CustomFeeModel(FeeModel):
def GetOrderFee(self, parameters):
fee = parameters.Security.Price * parameters.Order.AbsoluteQuantity * 0.00005
return OrderFee(CashAmount(fee, "USD"))