Created
October 13, 2018 14:36
-
-
Save StefanBelo/0bab566dd8bbbd20922c51eb7ccdef26 to your computer and use it in GitHub Desktop.
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
// Bfexplorer cannot be held responsible for any losses or damages incurred during the use of this betfair bot. | |
// It is up to you to determine the level of risk you wish to trade under. | |
// Do not gamble with money you cannot afford to lose. | |
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 System | |
open BeloSoft.Data | |
open BeloSoft.Bfexplorer.Domain | |
open BeloSoft.Bfexplorer.Trading | |
let getOddsDifference (selection1 : Selection, selection2 : Selection) = | |
selection1.OddsContext.GetOddsDifference(selection1.LastPriceTraded, selection2.LastPriceTraded) | |
let getBookValue (selections : Selection list) = | |
selections | |
|> List.map (fun mySelection -> toPriceProbability mySelection.LastPriceTraded) | |
|> List.sum | |
/// <summary> | |
/// TriggerStatus | |
/// </summary> | |
type TriggerStatus = | |
| Initialize | |
| WaitToPlaceBets | |
| WaitForBetsPlacing | |
| StartCloseBetPositionBot | |
| ReportError of string | |
/// <summary> | |
/// HorseRacingDutchTradingBotTrigger | |
/// </summary> | |
type HorseRacingDutchTradingBotTrigger(market : Market, _selection : Selection, _botName : string, botTriggerParameters : BotTriggerParameters, myBfexplorer : IMyBfexplorer) = | |
let mutable triggerStatus = TriggerStatus.Initialize | |
let mutable myFavourites = nil<Selection list> | |
let mutable initialBookValue = 0.0 | |
let timeToPlaceBets = market.MarketInfo.StartTime.AddMinutes(-(defaultArg (botTriggerParameters.GetParameter<float>("TimeToPlaceBets")) 2.0)) | |
let outputMessage message = | |
myBfexplorer.BfexplorerService.OutputMessage(message, market.Id) | |
let isHorseRacingMarket() = | |
market.MarketInfo.BetEventType.Id = 7 && market.MarketDescription.MarketType = "WIN" | |
let initialize() = | |
let minimumNumberOfRunners = defaultArg (botTriggerParameters.GetParameter<int>("MinimumNumberOfRunners")) 6 | |
let selections = | |
market.Selections | |
|> Seq.filter isNotRemovedSelection | |
|> Seq.sortBy (fun mySelection -> mySelection.LastPriceTraded) | |
|> Seq.toList | |
let numberOfRunners = selections.Length | |
if numberOfRunners >= minimumNumberOfRunners | |
then | |
let minimumRank = defaultArg (botTriggerParameters.GetParameter<byte>("MinimumRank")) 50uy | |
let maximumRank = defaultArg (botTriggerParameters.GetParameter<byte>("MaximumRank")) 150uy | |
myFavourites <- | |
selections | |
|> List.take 3 | |
|> List.choose (fun mySelection -> | |
maybe { | |
let! metaData = mySelection.MetaData | |
let horseRank = metaData.OfficialRating | |
if horseRank >= minimumRank && horseRank <= maximumRank | |
then | |
return mySelection | |
} | |
) | |
if myFavourites.Length = 3 | |
then | |
let minimumOddsDifference = defaultArg (botTriggerParameters.GetParameter<int>("MinimumOddsDifference")) 2 | |
let oddsDifference = getOddsDifference (myFavourites.[0], myFavourites.[1]) | |
if oddsDifference >= minimumOddsDifference | |
then | |
initialBookValue <- getBookValue myFavourites | |
true | |
else | |
outputMessage (sprintf "Not allowed odds difference: %d!" oddsDifference) | |
false | |
else | |
outputMessage "Horse/s not in allowed rank!" | |
false | |
else | |
outputMessage (sprintf "Not allowed number of runners: %d!" numberOfRunners) | |
false | |
let isTimeToPlaceBets() = | |
DateTime.Now >= timeToPlaceBets | |
let canPlaceDutchBets() = | |
let minimumBookDifference = defaultArg (botTriggerParameters.GetParameter<float>("MinimumBookDifference")) 0.1 | |
let bookValue = getBookValue myFavourites | |
let bookDifference = initialBookValue - bookValue | |
let status = bookDifference >= minimumBookDifference | |
if not status | |
then | |
outputMessage (sprintf "Book value: %.2f -> %.2f | %.2f" initialBookValue bookValue bookDifference) | |
status | |
let getBetsToDutch() = | |
let layPayout = defaultArg (botTriggerParameters.GetParameter<float>("LayPayout")) 5.0 | |
let selectionBetPriceSizes = | |
myFavourites | |
|> Seq.map (fun mySelection -> SelectionBetPriceSize(mySelection, BetType.Lay)) | |
|> Seq.toList | |
DutchingCalculations.CalculateForStakeToDutch(selectionBetPriceSizes, layPayout) |> ignore | |
selectionBetPriceSizes | |
|> List.map (fun selectionBetPriceSize -> selectionBetPriceSize.ToSelectionBetOrder()) | |
let betPlacedHandler (status : bool) = | |
triggerStatus <- | |
if status | |
then | |
TriggerStatus.StartCloseBetPositionBot | |
else | |
TriggerStatus.ReportError "Failed to place dutch bets!" | |
let startClosePositionOnMarketBot() = | |
let botParameters = ClosePositionOnMarketBotParameters() | |
let profit = defaultArg (botTriggerParameters.GetParameter<float>("Profit")) 5.0 | |
let loss = defaultArg (botTriggerParameters.GetParameter<float>("Loss")) 30.0 | |
botParameters.Name <- "Close my market bet position" | |
botParameters.Profit <- profit | |
botParameters.Loss <- loss | |
botParameters.ProfitOrLossInPercentage <- true | |
botParameters.CheckingLastPriceTraded <- false | |
botParameters.BetMatchingTimeout <- Nullable(TimeSpan.FromSeconds 2.0) | |
market |> addBot (ClosePositionOnMarketBot(market, botParameters, myBfexplorer.BfexplorerService)) | |
interface IBotTrigger with | |
/// <summary> | |
/// Execute | |
/// </summary> | |
member __.Execute() = | |
match triggerStatus with | |
| TriggerStatus.Initialize -> | |
if isHorseRacingMarket() | |
then | |
if initialize() | |
then | |
triggerStatus <- TriggerStatus.WaitToPlaceBets | |
TriggerResult.WaitingForOperation | |
else | |
TriggerResult.EndExecution | |
else | |
TriggerResult.EndExecutionWithMessage "You can execute this bot only on a horse racing market!" | |
| TriggerStatus.WaitToPlaceBets -> | |
if isTimeToPlaceBets() | |
then | |
if canPlaceDutchBets() | |
then | |
triggerStatus <- TriggerStatus.WaitForBetsPlacing | |
let betOrders = getBetsToDutch() | |
TriggerResult.PlaceBets (betOrders, PersistenceType.Persist, betPlacedHandler) | |
else | |
TriggerResult.EndExecutionWithMessage "Cannot place dutch bets!" | |
else | |
TriggerResult.WaitingForOperation | |
| TriggerStatus.WaitForBetsPlacing -> TriggerResult.WaitingForOperation | |
| TriggerStatus.StartCloseBetPositionBot -> | |
startClosePositionOnMarketBot() | |
TriggerResult.EndExecution | |
| TriggerStatus.ReportError errorMessage -> TriggerResult.EndExecutionWithMessage errorMessage | |
/// <summary> | |
/// EndExecution | |
/// </summary> | |
member __.EndExecution() = | |
() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment