-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Set final config for initla testing, confirmed scrapping running and owrking * Fetch analyzable data from postgres * Get trigram query working * Add matcher to three way game events as well * Get final ev tallies * Minor formatting * Display all ev results
- Loading branch information
1 parent
0e6f69c
commit 84b7e60
Showing
14 changed files
with
445 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import { getConfig } from "../.."; | ||
import { PostgresDataSourceSingleton } from "../../datastores/postgres"; | ||
import { ThreeWayGameEventEntity, TwoWayGameEventEntity } from "../../datastores/postgres/entities"; | ||
import { getAnalyzableTwoWayGames, getMatchingTwoWayGameEventsTrigram } from "../../datastores/postgres/queries/two_way_game_event"; | ||
import { Result } from "../../utils/types/result_type"; | ||
import { getAnalyzableThreeWayGames, getMatchingThreeWayGameEventsTrigram } from "../../datastores/postgres/queries/three_way_game_event"; | ||
|
||
const {logger} = getConfig(); | ||
|
||
export class BaseAnalyser { | ||
|
||
private getWinnings(stake: number, oddsForEvent: number): number { | ||
const totalWithdrawableOnWin = stake * oddsForEvent; | ||
return totalWithdrawableOnWin - stake; | ||
} | ||
|
||
/** | ||
* Gets the expected value of staking on an event. | ||
* Positive and higher results are better; | ||
* @param probabilityOfEvent "True" Probability between 0 and 1. | ||
* @param oddsForEvent Odds by the bet provider for the event. | ||
*/ | ||
protected getEventEvPercent(probabilityOfEvent: number, oddsForEvent: number): number { | ||
const theoreticalStake = 10; | ||
const evAsNumber = (this.getWinnings(theoreticalStake, oddsForEvent) * probabilityOfEvent) - (theoreticalStake * (1-probabilityOfEvent)); | ||
return evAsNumber; // TODO: Return as a percentage | ||
} | ||
/** | ||
* Get two way game events that can be analyzed. | ||
* Analyzable data is the data where the start event is greater than the current time. | ||
* | ||
* @param betType | ||
*/ | ||
protected async getTwoWayGameEventData(): Promise<Result<TwoWayGameEventEntity[], Error>> { | ||
const getPostgresDataSourceResult = await PostgresDataSourceSingleton.getInstance(getConfig()); | ||
if (getPostgresDataSourceResult.result === "error") { | ||
const message = "Failed to get postgres data source when fetching two way game events for analysis"; | ||
logger.error(message); | ||
return getPostgresDataSourceResult; | ||
} else { | ||
return { | ||
result: "success", | ||
value: await getAnalyzableTwoWayGames(getPostgresDataSourceResult.value) | ||
}; | ||
} | ||
} | ||
|
||
/** | ||
* Get three way game events that can be analyzed. | ||
* Analyzable data is the data where the start event is greater than the current time. | ||
* | ||
* @param betType | ||
*/ | ||
protected async getThreeWayGameEventData(): Promise<Result<ThreeWayGameEventEntity[], Error>> { | ||
const getPostgresDataSourceResult = await PostgresDataSourceSingleton.getInstance(getConfig()); | ||
if (getPostgresDataSourceResult.result === "error") { | ||
const message = "Failed to get postgres data source when fetching three way game events for analysis"; | ||
logger.error(message); | ||
return getPostgresDataSourceResult; | ||
} else { | ||
return { | ||
result: "success", | ||
value: await getAnalyzableThreeWayGames(getPostgresDataSourceResult.value) | ||
} | ||
} | ||
} | ||
|
||
protected async getMatchingTwoWayGameEvents(gameEvent: TwoWayGameEventEntity): Promise<Result<TwoWayGameEventEntity[] | null, Error>> { | ||
const getPostgresDataSourceResult = await PostgresDataSourceSingleton.getInstance(getConfig()); | ||
if (getPostgresDataSourceResult.result === "error") { | ||
const message = "Failed to get postgres data source when fetching matching game events for analysis"; | ||
logger.error(message); | ||
return getPostgresDataSourceResult; | ||
} else { | ||
return { | ||
result: "success", | ||
value: await getMatchingTwoWayGameEventsTrigram(getPostgresDataSourceResult.value, gameEvent) | ||
}; | ||
} | ||
} | ||
|
||
protected async getMatchingThreeWayGameEvents(gameEvent: ThreeWayGameEventEntity): Promise<Result<ThreeWayGameEventEntity[] | null, Error>> { | ||
const getPostgresDataSourceResult = await PostgresDataSourceSingleton.getInstance(getConfig()); | ||
if (getPostgresDataSourceResult.result === "error") { | ||
const message = "Failed to get postgres data source when fetching matching game events for analysis"; | ||
logger.error(message); | ||
return getPostgresDataSourceResult; | ||
} else { | ||
return { | ||
result: "success", | ||
value: await getMatchingThreeWayGameEventsTrigram(getPostgresDataSourceResult.value, gameEvent) | ||
}; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { BaseAnalyser } from ".."; | ||
import { getConfig } from "../../.."; | ||
import { ThreeWayGameEventEntity } from "../../../datastores/postgres/entities"; | ||
|
||
const {logger} = getConfig(); | ||
|
||
export class ThreeWayAnalyzer extends BaseAnalyser { | ||
public async getData() { | ||
const gameEventsWithEv: {clubAWinEv: number, clubBWinEv: number, drawEv: number, event: ThreeWayGameEventEntity}[] = []; | ||
|
||
const getEventDataResult = await this.getThreeWayGameEventData(); | ||
|
||
if (getEventDataResult.result === "error") { | ||
logger.error("Error while fetching event data: ", getEventDataResult.value.message); | ||
return; | ||
} | ||
|
||
const results = await getEventDataResult.value.map(async event => { | ||
const getMatchingEventsResult = await this.getMatchingThreeWayGameEvents(event); | ||
logger.info("Event: ", event); | ||
logger.info("Matching events: ", getMatchingEventsResult); | ||
|
||
if (getMatchingEventsResult.result === "success" && getMatchingEventsResult.value !== null) { | ||
getMatchingEventsResult.value.forEach(gameEvent => { | ||
const clubAWinTrueProbability = (1 / event.odds_a_win); | ||
const clubBWinTrueProbability = (1 / event.odds_b_win); | ||
const drawTrueProbability = (1 / event.odds_draw); | ||
|
||
const clubAWinEv = this.getEventEvPercent(clubAWinTrueProbability, gameEvent.odds_a_win); | ||
const clubBWinEv = this.getEventEvPercent(clubBWinTrueProbability, gameEvent.odds_b_win); | ||
const drawEv = this.getEventEvPercent(drawTrueProbability, gameEvent.odds_draw); | ||
|
||
gameEventsWithEv.push({ | ||
clubAWinEv, | ||
clubBWinEv, | ||
drawEv, | ||
event: gameEvent | ||
}); | ||
}); | ||
} | ||
}); | ||
|
||
await Promise.all(results); | ||
gameEventsWithEv.forEach(eventWithEv => { | ||
logger.info("Game event with EV: ", eventWithEv); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { BaseAnalyser } from ".."; | ||
import { getConfig } from "../../.."; | ||
import { TwoWayGameEventEntity } from "../../../datastores/postgres/entities"; | ||
|
||
const {logger} = getConfig(); | ||
|
||
export class TwoWayAnalyser extends BaseAnalyser { | ||
public async getData(): Promise<void> { | ||
const gameEventsWithEv: {clubAWinEv: Number, clubBWinEv: number, event: TwoWayGameEventEntity}[] = []; | ||
|
||
const getEventDataResult = await this.getTwoWayGameEventData(); | ||
|
||
if (getEventDataResult.result === "error") { | ||
logger.error("Error while fetching event data: ", getEventDataResult.value.message); | ||
return; | ||
} | ||
|
||
const results = await getEventDataResult.value.map(async event => { | ||
const getMatchingEventsResult = await this.getMatchingTwoWayGameEvents(event); | ||
logger.info("Event: ", event); | ||
logger.info("Matching events: ", getMatchingEventsResult); | ||
|
||
if (getMatchingEventsResult.result === "success" && getMatchingEventsResult.value !== null) { | ||
getMatchingEventsResult.value.forEach(gameEvent => { | ||
const clubAWinTrueProbability = (1 / event.odds_a_win); | ||
const clubBWinTrueProbability = (1 / event.odds_b_win); | ||
|
||
const clubAWinEv = this.getEventEvPercent(clubAWinTrueProbability, gameEvent.odds_a_win); | ||
const clubBWinEv = this.getEventEvPercent(clubBWinTrueProbability, gameEvent.odds_b_win); | ||
|
||
gameEventsWithEv.push({ | ||
clubAWinEv, | ||
clubBWinEv, | ||
event: gameEvent | ||
}); | ||
}); | ||
} | ||
}); | ||
|
||
await Promise.all(results); | ||
gameEventsWithEv.forEach(eventWithEv => { | ||
logger.info("Game event with EV: ", eventWithEv); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.