User Comments

  • Stefan
    4.11.2019 8:57:13

    I had already answered such question.

  • Stefan
    30.10.2019 13:07:48

    Please watch this video from my debugging of bot trigger code:

    Debugging Bot Trigger Code

    I set breakpoint, and add to watch view, selection and selection.BetPosition, so I could browse the watched object data, and see what properties are full with data.

    The similar dialog I added couple month ago to bfexplorer so you can browse some market and market selection data, to learn about bfexplorer data, and how/what you can use in your bot trigger code.

  • Stefan
    30.10.2019 11:07:59

    Have a look at the line 34:

    sprintf "%s: %A" selection.Name selection.BetPosition

    selection.BetPosition object offers your bet position, so please browse data, put their break point when dubbing your bot trigger code.

  • Stefan
    28.10.2019 16:01:12

    Yes, exactly. You simply must use correct wording. “Bets” is plural, right? So it is collection, not one bet. On the object property that is bet, you could do so: bet.Price and so on.

    I do not know what exactly you want to achieve as it is clear that you could have more unmatched bets on selection, so make reusable functions you could use/reuse in your bot triggers.

    I wanted to explain in my sample bot trigger code, how you can work on bfexplorer domain objects, so I used direct code, but if you try to write:  unmatched .. Visual Studio will offer you all available functions/types and so available for you after you

    open BeloSoft.Bfexplorer.Domain

    so surprising it is offered for you:

    isUnmatchedBet, unmatchedBetsExists, getBets, getUnmatchedBets, getUnmatchedBetsByBetType and so on and on.

    So code I already had wrote and is reusable.

    Then you could write:

    let layUnmtached = market.Bets |> getUnmatchedBetsByBetType BetType.Lay
    
    if not layUnmtached.IsEmpty
    
    then
    
        let firstUnmatched = layUnmtached.Head
    
        firstUnmatched.Price
    
        ...
    
  • Stefan
    28.10.2019 13:20:07

    Any code, in any programming language is “sentence” expressed by programming language “words” and constructs you can make by programming, adds the language vocabulary.

    So the vocabulary you can use to express your intentions in programming language is limited to couple words.

    The above line of code:

    let Stake = _selection.GetPriceSize(BetType.Lay)

    In human sentence expresses:

     Selection, get PriceSize object for Lay side to stake!

    As English have strict words order in sentence, to be grammatically correct, we command so exclamation mark at the end of sentence.

    So you command selection to get PriceSize, and in this context it is Lay PriceSize offered. It is not bet, it is offer on this selection other bettors placed.

    You can command bet object to get price or size to you, so odds or stake you placed a bet with.

    So you must ask/command _selection.Bets to get all unmatched bets to you (to value), and then ask a bet to get you price, size and so on, like I did in my bot trigger code:

    BetStatusBetCancellingBotOrchestrationBotTrigger.fsx

    on the line 31.

    *** 

    Read further only when you want to learn some advance features of F# programming language.

    ***

    I do not know in what context you use _selection, but please keep in mind that in F# underscore _ is used as intention to declare not used value, because in F# you must declare exact intention, so like in mathematics it does not make sense to express something what is not used.

    Yes, in other programming languages, programmers used to declare object variables with _, but in F# it has different meaning, for instance here:

    ShowPriceTradedVolume.fsx

    On the line 52, where I declared construct for BetStatusBetCancellingBotOrchestrationBotTrigger type, I used _ for not used values, because in F# any input value/s in constructor are declared as well as object values you can access not only in constructor but in entire type.

    On the line 106, you can see __ (two underscores), so in type member you must type __ to declare not used self-identifier of object. I use this as self-identifier, but you can use whatever word/character.

    Ok, this underscore issue is for advance developers, you code will work whatever you will use.

    ***

    Option value

    ***

    For the option types/values it is similar like in C# for Nullable. So you can use anOptionValue.IsSome and if is some you can get value by: anOptionValue.Value, but better way is to use match expression or functions from Option module, like Option.iter.

    In my code you can find maybe, computation expression I created, so for options you can type simplified expressions, for instance here:

    ShowHorseData.fsx

    Lines from 39 to 43, and then on line 40, let! ... actually evaluates if mySelection.MetaData.IsSome and continues only when it is assigning to metaData the value, otherwise returning None.

    Such expression allows me to write less code. Programming is not about writing a lot of code, actually less code is always better approach.

    Programming is about understanding of context in which you write the code, and so it is about interpreting of “words”.

  • Stefan
    28.10.2019 10:12:58

    Peter may I ask you to explain me by your own words, how do you understand this line of code?

    let Stake = _selection.GetPriceSize(BetType.Lay)

    As you may know, and now I speak not about programming languages, but about languages, my mother’s language is Slovak, and in many Slavic languages there is no such strict rule for word order like in English sentence.

    That is the funny part in your question, because well my understanding of any language construct is a little bit different from the way only English people could read the code, the sentence.

    Well, yes I understand what you want to try to do in your code, but the “words” you chose to do so are quite unclear for me.

  • Stefan
    27.10.2019 11:48:45

    this. is used to access object properties or methods.

    You type your code as you would access static method or type. You must type object, so in this case maybe: market.MarketInfo.StartTime

  • Stefan
    26.10.2019 14:17:38

    You can access market’s bets or selection’s bets directly (line 76 and 31), and for matched bets you can access BetPosition property, the line 79 and 34.

    BetPosition type/class allows you to calculate hedge stake and so on, have a look at on the type methods.

    To cancel bets you can use TriggerResult.CancelBets, the line 150.

    I already mentioned that the better way is to orchestrate existing bots to execute parts of your strategy, for instance you set trading bot and all bet placing/updating or cancelling your bets is then managed by this trading bot.

    In my bot trigger I showed what you asked and created such simple bots’ orchestration:

    BetStatusBetCancellingBotOrchestrationBotTrigger.fsx

    Please watch my video. To show how to cancel bets, I set my action bot: “Back 1 tick better”, so bot offers 2 Euro back bet 1 tick over best offered price. When odds changes and are in allowed odds range Minimum/MaximumOdds, the bot updates its unmatched bet to always offer its back bet 1 tick over the best offered, set by the parameter: PriceImprovemnt.

    Now, in my bot trigger I cancelled unmatched bet on my selection, the line 150. But what happened?

    As the bet was placed by my action bot, and the bot is managing its bets itself, the bet was again placed.

    What does it mean?

    If you place your bets by action bots, you do not need to manage bets placed by the action bot, but of course if you do not want your unmatched bets be offered on the market anymore, you need to stop the action bot, and as the action bot managing its bets, the unmatched bets will cancel its bets when you end its execution, the line 160.

    It is really better way to orchestrate action bots in your bot trigger than managing bet status in your bot trigger.

    Well yes, if you want to place your bets directly then you can do so, you have got:

    TriggerResult.PlaceBets

    TriggerResult.CancelBets

    Let’s say you have got strange trading strategy, where you setup the trading bot:

    "Place Bet and Close Selection Bet Position"

    To offer bet 3 ticks from best offered price, and close its bet position with profit of 3 ticks, or 5 ticks to lose.

    You would setup two versions of this trading bot one offering back and the other one lay bet. In your bot trigger you would execute such pair of trading bots on 3 favourites when some conditions occurred.

    Now imagine what you would have to program to manage such complex trading strategy in your bot trigger by directly placing your bets.

  • Stefan
    22.10.2019 15:55:27

    Here is my bot trigger code:

    ShowPriceTradedVolume.fsx

    Please watch video, showing how to use IntelliSense to browse available code.

  • Stefan
    22.10.2019 13:29:38

    Full market data are available in the active market, so in the only market open in Bet Event View or in Bet Event Trader View.

    Why is it so?

    Bfexplorer can monitor hundreds of markets so this way it is reasonably lower amount of data loaded from betfair servers.

    Yes you can get matched volume only through PriceGridData, of course you must iterate through prices with traded volume, not all of 399 prices are traded.

    If you run your bot in Bot Executor, then you can simply use the bot: “Execute at Time” and set the parameter: UseSetMarketInactive to True. So when executed in bot executes your action bot and set MonitoringStatus to Inactive, Bot Executor then removes such market from monitoring and opens it in Bet Event view, so your bot have them full market data available.

    Of course there are other betfair api methods you can use to get traded data betfair uses in charts. You can see that in my post:

    Lay the Field Strategy – Analyzing Data

  • Stefan
    20.10.2019 15:27:07

    Here is my bot trigger showing on ladders near BSP and after the race is turned at in-play the actual BSP:

    HorseRacingShowStartPrices.fsx

  • Stefan
    20.10.2019 10:38:19

    Actually, there are such bot triggers:

    HorseRacingSpFavouriteBotTrigger.fsx

    HorseRacingSpBotTrigger.fsx

    As an example you could create a bot trigger showing for active selections near BSP and actual BSP after race is turned at in-play. You can show prices on ladder, like in this example:

    Horse Racing - Oddschecker Favourite Trigger

  • Stefan
    20.10.2019 10:24:09

    Yes, placing betfair sp bet returns matched bet with matched amount zero, as SP bet is fully matched only after race is turned at in-play and all betfair start price bets are processed.  This be cannot be cancelled I believe, well have never try that.

    You can place normal bet with Take SP, such bet can be cancelled and unmatched part of bet is turned to SP at the moment race is turned at in-play.

    Have a look at UpdateSpPricesMarketBot.fs if you want to update sp prices, but that is bot assembly, not bot trigger code. You have got access to betfair api in bot trigger code, so you need to study betfair documentation and then you can replicated code working with sp prices in bot trigger as well.

     

  • Stefan
    17.10.2019 9:41:41

    That is great Peter.

    I would really suggest you to set breakpoint in your code and then debug it and browse available data offered by bfexplorer.

    You must know what data you have got, visualize them in your head, and then you know what you can do with data.

    Your approach for now is browsing existing code, so when you did not find similar one you cannot make progress, but data you have got, so working with data is the way to go.

  • Stefan
    16.10.2019 20:38:18

    On the line 3 of your code, there are set three values: startIndex, nextIndex, findFun

    The findFun is function used to evaluate the place with empty offer. So when you want to place back bet, it must be checked lay offer and wise versa.

    You change that code, therefore your findFun function returns true on offer with available offer. Actually in your code I cannot see logical problem because you start iterating through data on the best offer, so price must be set.

    If you code does not go to the line 23, as you say price returned is always 0.0

    Peter, how/where you execute your bot trigger?

    The full market depth is updated only for active market, so for the market that is currently open in Bet Event/Trader.

    It means that if you run your bot by Bot Executor tool you will get updates only for 3 best offered prices.

    I would suggest you to debug code, only this way you can find your problem in the code.

    Hint: There is function selection.PriceGridData.GetOfferedPriceData()

    You can use to get all offered prices. I do not know what you want to make in your code, so this function: GetOfferedPriceData returns all offered prices, and you can filter whatever criteria you use.

    Here is bot trigger code:

    ShowOfferedPrices.fsx

    Peter, please use VS debugger when testing your code.

  • Stefan
    14.10.2019 13:04:41

    I have just updated Bfexplorer BOT SDK source code adding MyFootballStrategy projects showing how to use Bfexplorer Plugin integration.

    The MyFootballStrategy.App is working example. If you trade football matches on betfair you can use it to monitor all matches live score and match statistics.

    https://github.com/StefanBelo/Bfexplorer-BOT-SDK/tree/master/MyFootballStrategy

    If anyone wants to collaborate on this project adding new features, and is able to program, then of course you can clone entire Bfexplorer BOT SDK solution.

    Those of you who just want to use this app, and are not able to build plugin from the source code, just contact me through support page and I will send you app/plugin files.

  • Stefan
    14.10.2019 10:29:39

    One of TriggerResult discriminated unions entry is:

    TriggerResult.OpenAssociatedMarkets of string[] * (DataResult<Market list> -> unit)

    Allowing requesting associated markets to the market you are running your bot on.

    Every market is open as bet event on betfair, and you have got access to this information:

    market.MarketInfo.BetEvent

    So bfexplorer when you request TriggerResult.OpenAssociatedMarkets knows for which bet event id the associated markets should be queried.

    Please have a look at on this bot trigger script:

    HorseRacingWinToBePlacedData.fsx

    Basically your bot has access to all betfair api methods:

    myBfexplorer.BfexplorerService.BetfairServiceProvider

    So you could be able to write any code against betfair api. The question is, is this approach practical?

    Your bot is executed on exact type of market, for instance on horse racing win market, so what markets would you like to open in Bet Event view? Tennis match odds market, or football match odds market?

    In any such scenario common sense dictates that you want to open associated market for bet event on which your bot is running, for instance place horse racing market, when your bot runs on win horse racing market and so on.

    If you want to build your bespoke app on bfexplorer app, you can do so like I present in this article:

    Bfexplorer Plugin Support

  • Stefan
    11.10.2019 12:13:53

    Peter, post on github your code you want to review, and please add to files extension, then github code preview can highlight the syntax, as from ending .fs, or ,fsx it is known that code is F#.

    You can debug your code in Visual Studio, so you can really test each line of your bot trigger code, and so learn how your code works.

  • Stefan
    11.10.2019 10:28:42

    I created ScalpingTradingStrategyBot.fsx bot trigger as a case study for some trading strategy I read about on other forum. Unfortunately I forget to put link to that forum but posted on my blog this article:

    Greyhounds Racing - Scalping Trading Strategy Bot

    Please read it first if you did not do so before.

    So in the bot trigger code I created MyTraderBot taking selection and stake amount as entry parameters, lines from 50 (the bot constructor) to 86.

    As mentioned MyTraderBot orchestrates two “PlaceBetBot”s The parameter setting is created by function createBotParameters, lines from 27 to 38. As you may noticed (have a look at on the line 52) any bfexplorer bot is created as bot type, and uses its parameters, so in this case for PlaceBetBot, there is bot implementation type PlaceBetBot, and parameters the type (class) PlaceBetBotParameters. PlaceBetBot implements all bot logic, and parameters just describer set of parameters the bot can use, for instance BetType and Stake the bot places bet with.

    Bot must be executed on exact market and selection, therefore for instance of the bot object is created (lines 52 and 53), the bot comstructor takes market, selection, botPrameters and bfexplorerService.

    BfexplorerService object implements betfair api and application domain. When you run your bot trigger, actually your code uses BfexplorerService to interact with betfair api.

    The other used bot is: ClosePositionOnMarketBot, and from the name of this bot type, you can judge what this bot does. Therefore the bot constructor does not take any selection as entry value. The bot parameters are implemented by type: ClosePositionOnMarketBotParameters.

    The bot closes bet position when required profit is reached (Profit parameter, the line 102), and well ends execution of all running bots, that is executed before the bet closes selections bet position.

    Finally fot trigger code, the lines from 133 to 159. When bot trigger is executed, on all active selections there is created instance of MyTraderBot and one instance of ClosePositionOnMarketBot, the code line 145. When checking the code in createMyBots function, you can see that starting a bot is done by adding to the market, the line 111, the same in lines 65 and 66.

    When is actually your bot executed?

    Well, it is done by BfexplorerService after market prices have been updated, your bot is actually just object instance, and its execution time is limited only by short time when BfexplorerService updates entire status of market and bets data.

    The bot strategy is to place back and lay bets on selections, and as the bets are placed by PlaceBetBot, we need to update range of allowed odds range, the lines from 68 to 86, the method Update. We need to update this parameters on for running bots, lines from 149 to 153.

    Why bot trigger ScalpingTradingStrategyBot does not implement any logic to ends its execution? It can be simply done by checking if there is still MyTraderBot running on some selection.

    Well, because we orchestrate in this case two types of bots, and one of them closes/ends execution of all other bots before closing bet position on the market.

    This bot trigger code is nice example of advantages of using bfexplorer action bots, as nay strategy can be executed by these action bots. Your trigger strategy should define/implements just entry and exit criteria in time. The rest is executed by action bots.

    Use the code only as inspiration, as there is no logic in entry points implemented by MyTraderBot.

  • Stefan
    10.10.2019 13:50:57

    I do not understand in what context you want to execute your bots and what method you want to use, because ScalpingTradingStrategyBot.fsx uses direct initialization of PlaceBet bot instances and ClosePositionOnMarketBot bot instance.

    For now you worked only with action bots, changing their parameters.

    Why do you need directly to create your bots?

    In your bot trigger code I already mentioned that you repeat the code, is the question about this issue?