|
|
@@ -4,8 +4,13 @@ import java.sql.Connection;
|
|
|
import java.sql.PreparedStatement;
|
|
|
import java.sql.ResultSet;
|
|
|
import java.sql.SQLException;
|
|
|
+import java.time.LocalDate;
|
|
|
import java.time.LocalDateTime;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
import java.util.ArrayList;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.List;
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
import com.google.common.collect.Lists;
|
|
|
|
|
|
@@ -24,7 +29,17 @@ public abstract class TestClass {
|
|
|
int sportId;
|
|
|
int countryId;
|
|
|
int leagueId;
|
|
|
+ protected int bestAwayLookback;
|
|
|
+ protected int bestAwayMargin;
|
|
|
+ protected int bestDrawMargin;
|
|
|
+ protected int bestDrawLookback;
|
|
|
+ protected int bestHomeMargin;
|
|
|
+ protected int bestHomeLookback;
|
|
|
+ protected float bestDrawBank;
|
|
|
+ protected float bestAwayBank;
|
|
|
+ protected float bestHomeBank;
|
|
|
|
|
|
+ ArrayList<results> possitiveResults = new ArrayList<>();
|
|
|
|
|
|
public abstract void runTest();
|
|
|
|
|
|
@@ -91,4 +106,313 @@ public abstract class TestClass {
|
|
|
public League getLeagueInfoByName(String leagueName) {
|
|
|
return GuiMysql.getInstance().getLeagueInfo(leagueName);
|
|
|
}
|
|
|
+
|
|
|
+ public void CalculateLookback(int leagueId, LocalDateTime date, int daysToCheck) {
|
|
|
+ final LocalDateTime startDate = date.minusDays(daysToCheck);
|
|
|
+ final String sql = "SELECT res.*, "
|
|
|
+ + "hTeam.name as homeTeamName, aTeam.name as awayTeamName "
|
|
|
+ + "FROM SoccerResults as res "
|
|
|
+ + "Join Team as hTeam ON res.homeTeam = hTeam.id "
|
|
|
+ + "Join Team as aTeam ON res.awayTeam = aTeam.id "
|
|
|
+ + "WHERE res.leagueId = ? AND DATE(gameDate) < ? AND DATE(gameDate) > ? ORDER BY gameDate ASC";
|
|
|
+
|
|
|
+ try {
|
|
|
+ final PreparedStatement stmt = getConnection().prepareStatement(sql);
|
|
|
+ stmt.setInt(1, leagueId);
|
|
|
+ stmt.setString(2, date.format(DateTimeFormatter.ISO_DATE));
|
|
|
+ stmt.setString(3, startDate.format(DateTimeFormatter.ISO_DATE));
|
|
|
+
|
|
|
+ final ArrayList<SoccerMatch> matches = getMatches(stmt);
|
|
|
+ stmt.close();
|
|
|
+
|
|
|
+ if (matches.size() > 0) {
|
|
|
+ this.bestHomeBank = startingBank;
|
|
|
+ this.bestDrawBank = startingBank;
|
|
|
+ this.bestAwayBank = startingBank;
|
|
|
+
|
|
|
+ // TODO Fixa så att man kontrollerar 1 år bakåt i tiden som Filtered Matches,
|
|
|
+ // plocka bort om possitive results är färre än 50%
|
|
|
+ recalcHome(matches);
|
|
|
+ recalcDraw(matches);
|
|
|
+ recalcAway(matches);
|
|
|
+ }
|
|
|
+ } catch (final SQLException e) {
|
|
|
+ // TODO Auto-generated catch block
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void recalcHome(ArrayList<SoccerMatch> matches) {
|
|
|
+ if (this.bestHomeBank < 0) {
|
|
|
+ this.bestHomeBank = startingBank;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.bestHomeLookback = 0;
|
|
|
+ this.bestHomeMargin = 0;
|
|
|
+
|
|
|
+ final float betLevel = bettingLevel / 100f;
|
|
|
+
|
|
|
+ final LocalDateTime currentDate = matches.get(0).getGameDate();
|
|
|
+ LocalDate localDate = currentDate.toLocalDate();
|
|
|
+ float betAmount = startingBank * betLevel;
|
|
|
+
|
|
|
+ possitiveResults.clear();
|
|
|
+
|
|
|
+ for (int lookBack = 4; lookBack < 25; lookBack++) {
|
|
|
+ for (int betMargin = 4; betMargin < 35; betMargin++) {
|
|
|
+ final float betMarginDecimal = 1 + (betMargin / (float)100);
|
|
|
+ float bank = startingBank;
|
|
|
+ for (final SoccerMatch match : matches) {
|
|
|
+ if (match.getHomeScore() < 0 || match.getAwayScore() < 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ final List<SoccerMatch> homeMatches = matches.stream().filter(p -> p.getGameDate().isBefore(match.getGameDate()) && p.getHomeTeam().getTeamId() == match.getHomeTeam().getTeamId()).limit(lookBack).collect(Collectors.toList());
|
|
|
+ final List<SoccerMatch> awayMatches = matches.stream().filter(p -> p.getGameDate().isBefore(match.getGameDate()) && p.getAwayTeam().getTeamId() == match.getAwayTeam().getTeamId()).limit(lookBack).collect(Collectors.toList());
|
|
|
+
|
|
|
+ final long hemmaVinster = homeMatches.stream().filter(p -> p.getHomeScore() > p.getAwayScore()).count();
|
|
|
+ final long bortaForluster = awayMatches.stream().filter(p -> p.getAwayScore() < p.getHomeScore()).count();
|
|
|
+
|
|
|
+ final float homeWinPercent = (hemmaVinster + bortaForluster) / Float.valueOf(homeMatches.size() + awayMatches.size()) * 100;
|
|
|
+ final float homeOdds = 100 / homeWinPercent;
|
|
|
+
|
|
|
+ if (localDate.isBefore(match.getGameDate().toLocalDate())) {
|
|
|
+ betAmount = bank * betLevel;
|
|
|
+ localDate = match.getGameDate().toLocalDate();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (homeOdds * betMarginDecimal <= match.getOdds1()) {
|
|
|
+ bank = bank - betAmount;
|
|
|
+ if (match.getHomeScore() > match.getAwayScore()) {
|
|
|
+ bank = bank + betAmount * match.getOdds1();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ if (bank > startingBank) {
|
|
|
+ final int lookBack2 = lookBack;
|
|
|
+ final int betMargin2 = betMargin;
|
|
|
+ final java.util.Optional<results> found = possitiveResults.stream().filter(r -> r.getLookback() == lookBack2 && r.getMargin() == betMargin2).findFirst();
|
|
|
+ if (found.isPresent()) {
|
|
|
+ final results results = found.get();
|
|
|
+ results.addCount();
|
|
|
+ results.addBank(bank);
|
|
|
+ } else {
|
|
|
+ possitiveResults.add(new results(lookBack, betMargin, bank));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Collections.sort(possitiveResults);
|
|
|
+ if (possitiveResults.size() > 0) {
|
|
|
+ final results res = possitiveResults.get(0);
|
|
|
+ this.bestHomeLookback = res.getLookback();
|
|
|
+ this.bestHomeMargin = res.getMargin();
|
|
|
+ this.bestHomeBank = res.getBank();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void recalcDraw(ArrayList<SoccerMatch> matches) {
|
|
|
+ if (this.bestDrawBank < 0) {
|
|
|
+ this.bestDrawBank = startingBank;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.bestDrawLookback = 0;
|
|
|
+ this.bestDrawMargin = 0;
|
|
|
+
|
|
|
+ final float betLevel = bettingLevel / 100f;
|
|
|
+
|
|
|
+ final LocalDateTime currentDate = matches.get(0).getGameDate();
|
|
|
+ LocalDate localDate = currentDate.toLocalDate();
|
|
|
+ float betAmount = startingBank * betLevel;
|
|
|
+
|
|
|
+ possitiveResults.clear();
|
|
|
+
|
|
|
+ for (int lookBack = 4; lookBack < 25; lookBack++) {
|
|
|
+ for (int betMargin = 4; betMargin < 35; betMargin++) {
|
|
|
+ final float betMarginDecimal = 1 + (betMargin / (float)100);
|
|
|
+ float bank = startingBank;
|
|
|
+ for (final SoccerMatch match : matches) {
|
|
|
+ if (match.getHomeScore() < 0 || match.getAwayScore() < 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ final List<SoccerMatch> homeMatches = matches.stream().filter(p -> p.getGameDate().isBefore(match.getGameDate()) && p.getHomeTeam().getTeamId() == match.getHomeTeam().getTeamId()).limit(lookBack).collect(Collectors.toList());
|
|
|
+ final List<SoccerMatch> awayMatches = matches.stream().filter(p -> p.getGameDate().isBefore(match.getGameDate()) && p.getAwayTeam().getTeamId() == match.getAwayTeam().getTeamId()).limit(lookBack).collect(Collectors.toList());
|
|
|
+
|
|
|
+ final long hemmaLika = homeMatches.stream().filter(p -> p.getHomeScore() == p.getAwayScore()).count();
|
|
|
+ final long bortaLika = awayMatches.stream().filter(p -> p.getAwayScore() == p.getHomeScore()).count();
|
|
|
+
|
|
|
+ final float drawPercent = (hemmaLika + bortaLika) / Float.valueOf(homeMatches.size() + awayMatches.size()) * 100;
|
|
|
+ final float drawOdds = 100 / drawPercent;
|
|
|
+
|
|
|
+ if (localDate.isBefore(match.getGameDate().toLocalDate())) {
|
|
|
+ betAmount = bank * betLevel;
|
|
|
+ localDate = match.getGameDate().toLocalDate();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (drawOdds * betMarginDecimal <= match.getOddsX()) {
|
|
|
+ bank = bank - betAmount;
|
|
|
+ if (match.getHomeScore() == match.getAwayScore()) {
|
|
|
+ bank = bank + betAmount * match.getOddsX();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ if (bank > startingBank) {
|
|
|
+ final int lookBack2 = lookBack;
|
|
|
+ final int betMargin2 = betMargin;
|
|
|
+ final java.util.Optional<results> found = possitiveResults.stream().filter(r -> r.getLookback() == lookBack2 && r.getMargin() == betMargin2).findFirst();
|
|
|
+ if (found.isPresent()) {
|
|
|
+ final results results = found.get();
|
|
|
+ results.addCount();
|
|
|
+ results.addBank(bank);
|
|
|
+ } else {
|
|
|
+ possitiveResults.add(new results(lookBack, betMargin, bank));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Collections.sort(possitiveResults);
|
|
|
+ if (possitiveResults.size() > 0) {
|
|
|
+ final results res = possitiveResults.get(0);
|
|
|
+ this.bestDrawLookback = res.getLookback();
|
|
|
+ this.bestDrawMargin = res.getMargin();
|
|
|
+ this.bestDrawBank = res.getBank();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void recalcAway(ArrayList<SoccerMatch> matches) {
|
|
|
+ if (this.bestAwayBank < 0) {
|
|
|
+ this.bestAwayBank = startingBank;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.bestAwayLookback = 0;
|
|
|
+ this.bestAwayMargin = 0;
|
|
|
+
|
|
|
+ final float betLevel = bettingLevel / 100f;
|
|
|
+
|
|
|
+ final LocalDateTime currentDate = matches.get(0).getGameDate();
|
|
|
+ LocalDate localDate = currentDate.toLocalDate();
|
|
|
+ float betAmount = startingBank * betLevel;
|
|
|
+
|
|
|
+ possitiveResults.clear();
|
|
|
+
|
|
|
+ for (int lookBack = 4; lookBack < 25; lookBack++) {
|
|
|
+ for (int betMargin = 4; betMargin < 35; betMargin++) {
|
|
|
+ final float betMarginDecimal = 1 + (betMargin / (float)100);
|
|
|
+ float bank = startingBank;
|
|
|
+ for (final SoccerMatch match : matches) {
|
|
|
+ if (match.getHomeScore() < 0 || match.getAwayScore() < 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ final List<SoccerMatch> homeMatches = matches.stream().filter(p -> p.getGameDate().isBefore(match.getGameDate()) && p.getHomeTeam().getTeamId() == match.getHomeTeam().getTeamId()).limit(lookBack).collect(Collectors.toList());
|
|
|
+ final List<SoccerMatch> awayMatches = matches.stream().filter(p -> p.getGameDate().isBefore(match.getGameDate()) && p.getAwayTeam().getTeamId() == match.getAwayTeam().getTeamId()).limit(lookBack).collect(Collectors.toList());
|
|
|
+
|
|
|
+ final long hemmaForluster = homeMatches.stream().filter(p -> p.getHomeScore() < p.getAwayScore()).count();
|
|
|
+ final long bortaVinster = awayMatches.stream().filter(p -> p.getAwayScore() > p.getHomeScore()).count();
|
|
|
+
|
|
|
+ final float awayWinPercent = (hemmaForluster + bortaVinster) / Float.valueOf(homeMatches.size() + awayMatches.size()) * 100;
|
|
|
+ final float awayOdds = 100 / awayWinPercent;
|
|
|
+
|
|
|
+ if (localDate.isBefore(match.getGameDate().toLocalDate())) {
|
|
|
+ betAmount = bank * betLevel;
|
|
|
+ localDate = match.getGameDate().toLocalDate();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (awayOdds * betMarginDecimal <= match.getOdds2()) {
|
|
|
+ bank = bank - betAmount;
|
|
|
+ if (match.getHomeScore() < match.getAwayScore()) {
|
|
|
+ bank = bank + betAmount * match.getOdds2();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if (bank > startingBank) {
|
|
|
+ final int lookBack2 = lookBack;
|
|
|
+ final int betMargin2 = betMargin;
|
|
|
+ final java.util.Optional<results> found = possitiveResults.stream().filter(r -> r.getLookback() == lookBack2 && r.getMargin() == betMargin2).findFirst();
|
|
|
+ if (found.isPresent()) {
|
|
|
+ final results results = found.get();
|
|
|
+ results.addCount();
|
|
|
+ results.addBank(bank);
|
|
|
+ } else {
|
|
|
+ possitiveResults.add(new results(lookBack, betMargin, bank));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Collections.sort(possitiveResults);
|
|
|
+ if (possitiveResults.size() > 0) {
|
|
|
+ final results res = possitiveResults.get(0);
|
|
|
+ this.bestAwayLookback = res.getLookback();
|
|
|
+ this.bestAwayMargin = res.getMargin();
|
|
|
+ this.bestAwayBank = res.getBank();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class results implements Comparable<results> {
|
|
|
+ int lookback;
|
|
|
+ int margin;
|
|
|
+ int count;
|
|
|
+ float bank;
|
|
|
+
|
|
|
+ public results(int lookback, int margin, float bank) {
|
|
|
+ this.lookback = lookback;
|
|
|
+ this.margin = margin;
|
|
|
+ this.bank = bank;
|
|
|
+ count = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ public float getBank() {
|
|
|
+ return bank;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void addBank(float bank) {
|
|
|
+ this.bank = (this.bank + bank) / 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void addCount() {
|
|
|
+ count++;
|
|
|
+ }
|
|
|
+ public int getCount() {
|
|
|
+ return count;
|
|
|
+ }
|
|
|
+
|
|
|
+ public int getLookback() {
|
|
|
+ return lookback;
|
|
|
+ }
|
|
|
+ public int getMargin() {
|
|
|
+ return margin;
|
|
|
+ }
|
|
|
+ public void setLookback(int lookback) {
|
|
|
+ this.lookback = lookback;
|
|
|
+ }
|
|
|
+ public void setMargin(int margin) {
|
|
|
+ this.margin = margin;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int compareTo(results res) {
|
|
|
+ int returnValue = 0;
|
|
|
+ if (this.count > res.getCount()) {
|
|
|
+ returnValue = -1;
|
|
|
+ } else if (this.count == res.getCount()) {
|
|
|
+ if (this.bank > res.getBank()) {
|
|
|
+ returnValue = -1;
|
|
|
+ } else if (this.bank < res.getBank()) {
|
|
|
+ returnValue = 1;
|
|
|
+ } else {
|
|
|
+ returnValue = 0;
|
|
|
+ }
|
|
|
+ } else if (this.count < res.getCount()) {
|
|
|
+ returnValue = 1;
|
|
|
+ }
|
|
|
+ return returnValue;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|