Skip to content

Instantly share code, notes, and snippets.

@StefanBelo
Last active December 21, 2018 13:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StefanBelo/3baa73a8a33adb5147fecd4d75bf22ed to your computer and use it in GitHub Desktop.
Save StefanBelo/3baa73a8a33adb5147fecd4d75bf22ed to your computer and use it in GitHub Desktop.
module BfexplorerBot
#I @"C:\Program Files (x86)\BeloSoft\Bfexplorer\"
#r "BeloSoft.Data.dll"
#r "BeloSoft.Betfair.API.dll"
#r "BeloSoft.Bfexplorer.Domain.dll"
#r "BeloSoft.Bfexplorer.Trading.dll"
#r "BeloSoft.Bfexplorer.Service.Core.dll"
open BeloSoft.Data
open BeloSoft.Betfair
open BeloSoft.Bfexplorer.Domain
open BeloSoft.Bfexplorer.Trading
/// <summary>
/// BetfairSpPrice
/// </summary>
type BetfairSpPrice() =
member val ActualSP : float = 0.0 with get, set
static member DataKey = "bsp"
static member Set (selection : Selection) =
selection.SetData(BetfairSpPrice.DataKey, BetfairSpPrice())
static member Get (selection : Selection) =
selection.GetData<BetfairSpPrice>(BetfairSpPrice.DataKey)
/// <summary>
/// MySelectionData
/// </summary>
type MySelectionData(selection : Selection, spPrice : float) =
let mutable triggerPriceValue : float option = None
let mutable triggerOddsDifferenceCrossed = false
member _this.Selection
with get() = selection
member _this.SpPrice
with get() = spPrice
member _this.CanExecute
with get() = triggerOddsDifferenceCrossed
member _this.Update(triggerPrice : float, triggerOddsDifference : int) =
let price = selection.LastPriceTraded
match triggerPriceValue with
| Some myTriggerPrice ->
let oddsDifference = selection.OddsContext.GetOddsDifference(myTriggerPrice, price)
triggerOddsDifferenceCrossed <- oddsDifference >= triggerOddsDifference
| None ->
if price <= triggerPrice
then
triggerPriceValue <- Some price
/// <summary>
/// updateSelectionSpPrice
/// </summary>
/// <param name="selection"></param>
/// <param name="runner"></param>
let updateSelectionSpPrice (selection : Selection, runner : API.Models.Runner) =
BetfairSpPrice.Get selection
|> Option.iter (fun betfairSpPrices ->
let spPrices = runner.sp
betfairSpPrices.ActualSP <- spPrices.actualSP
)
/// <summary>
/// TriggerStatus
/// </summary>
type TriggerStatus =
| Initialize
| WaitForInPlay
| WaitForUpdateSpPrices
| ReportSpPrices
| WaitToTriggerActionBot
| ReportError of string
/// <summary>
/// HorseRacingSpFavouriteBotTrigger
/// </summary>
type HorseRacingSpFavouriteBotTrigger(market : Market, _selection : Selection, _botName : string, botTriggerParameters : BotTriggerParameters, myBfexplorer : IMyBfexplorer) =
let favouriteSpPrice = defaultArg (botTriggerParameters.GetParameter<float>("FavouriteSpPrice")) 2.0
let myHorsesSpPrice = defaultArg (botTriggerParameters.GetParameter<float>("MyHorsesSpPrice")) 7.0
let triggerPrice = defaultArg (botTriggerParameters.GetParameter<float>("TriggerPrice")) 3.0
let triggerOddsDifference = defaultArg (botTriggerParameters.GetParameter<int>("TriggerOddsDifference")) 5
let mutable status = TriggerStatus.Initialize
let mutable mySelectionsDatas = nil<MySelectionData list>
let outputMessage message =
myBfexplorer.BfexplorerService.OutputMessage(message, market.Id)
let getMySelectionsDatas() =
market.Selections
|> Seq.choose (fun selection ->
match BetfairSpPrice.Get selection with
| Some betfairSpPrice ->
let spPrice = betfairSpPrice.ActualSP
if spPrice = 0.0
then
None
else
Some (MySelectionData(selection, spPrice))
| None -> None
)
|> Seq.sortBy (fun mySelectionData -> mySelectionData.SpPrice)
|> Seq.toList
let showHorsesData (selectionsDatas : MySelectionData list) =
selectionsDatas
|> List.map (fun selectionData -> sprintf "%s: %.2f" selectionData.Selection.Name selectionData.SpPrice)
|> String.concat "\n"
|> outputMessage
let canExecuteMyStrategy (selectionsDatas : MySelectionData list) =
let favourite = selectionsDatas.Head
favourite.SpPrice <= favouriteSpPrice
let getMySelectionsDatasToWatch (selectionsDatas : MySelectionData list) =
selectionsDatas |> List.filter (fun selectionData -> selectionData.SpPrice >= myHorsesSpPrice)
let getMySelection() =
mySelectionsDatas |> List.iter (fun mySelectionsData -> mySelectionsData.Update(triggerPrice, triggerOddsDifference))
mySelectionsDatas |> List.tryFind (fun mySelectionsData -> mySelectionsData.CanExecute)
interface IBotTrigger with
member __.Execute() =
match status with
| TriggerStatus.Initialize ->
if market.MarketInfo.BetEventType.Id = 7
then
status <- TriggerStatus.WaitForInPlay
market.Selections
|> Seq.filter isActiveSelection
|> Seq.iter BetfairSpPrice.Set
TriggerResult.WaitingForOperation
else
TriggerResult.EndExecutionWithMessage "You can run this bot on a horse racing market only!"
| TriggerStatus.WaitForInPlay ->
if market.IsInPlay
then
status <- TriggerStatus.WaitForUpdateSpPrices
async {
let! result = myBfexplorer.BfexplorerService.UpdateMarketData(market, API.Models.PriceProjection.DefaultBetfairSpPrice(), updateSelectionSpPrice)
status <-
if result.IsSuccessResult
then
TriggerStatus.ReportSpPrices
else
TriggerStatus.ReportError result.FailureMessage
}
|> Async.Start
TriggerResult.WaitingForOperation
| TriggerStatus.WaitForUpdateSpPrices -> TriggerResult.WaitingForOperation
| TriggerStatus.ReportSpPrices ->
let selectionsDatas = getMySelectionsDatas()
showHorsesData selectionsDatas
if canExecuteMyStrategy selectionsDatas
then
mySelectionsDatas <- getMySelectionsDatasToWatch selectionsDatas
if mySelectionsDatas.Length > 0
then
status <- TriggerStatus.WaitToTriggerActionBot
TriggerResult.WaitingForOperation
else
TriggerResult.EndExecution
else
TriggerResult.EndExecution
| TriggerStatus.WaitToTriggerActionBot ->
match getMySelection() with
| Some mySelectionData -> TriggerResult.ExecuteActionBotOnSelection mySelectionData.Selection
| None -> TriggerResult.WaitingForOperation
| TriggerStatus.ReportError errorMessage -> TriggerResult.EndExecutionWithMessage errorMessage
member __.EndExecution() =
()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment