Article

Bot Trigger Building Part 2

Now that the selection has been identified (in Part 1, a horse in lane x in a race with more than x selections), I'd like some triggers to be met before initiating a trade.

Firstly, for this example, I'd like to place a lay bet only when the horse has odds in range 10 to 20 when the following 2 triggers are met:

1- Our selection has dropped in position since X seconds in play.

2- The number 1 and 2 position horses both have back odds less then 2 (and our selection is not position 1,2 or 3)

So after Part 2, we have a working bot that will execute a lay bet within odds range of 10 to 20 on our selection (based on the 2 triggers in Part 1) ONLY IF the 2 triggers in Part 2 are true

Comments ( 19 )


  • Stefan
    1.10.2019 10:16:13

    Peter, it is up to you what homework you do, or what different bot trigger you could offer for other readers, as your bot trigger can evaluate different selection values, and as well evaluation process could be programmed by many different ways.

    I actually separated storing of selection trigger values to different type/class, so code is prepared for different scenarios.

    If you really are able to read the trigger bot code you have to see it, so you can describe those different scenarios to others, but that is up to you.

    I asked for “homework” because you reported problems with compiling bot trigger code, what means you did not understand what were you doing, I hope you do now.

  • peteresgate@outlook.com
    1.10.2019 10:24:50

    Thanks Stefan.  I do have more understanding now, but have a long long way to go.  Thanks for your help.  With Part 4 in which the bot "counts" it's losses before shutting down, is this possible?  I question it because I see in the console bot started and bot ended, so I don't understand the mechanism of how it stores the losses if the bot ends.

  • Stefan
    1.10.2019 11:17:49

    With anything you do, you need at least base understanding of what you do.

    If you go with Excel automation to place your bets on betfair, then you need to learn how to use Excel, formulas, and of course VBA programming, because you cannot make running your strategy just by using formulas, or bet angel rules.

    To part 4 of your tutorial, without saying anything about coding, just use common sense to understand what should be done.

    If your strategy depends on previous results, then of course something in bfexplorer should be able to retrieve your bet results, and process this information. Your bot trigger must be able to work with such information.

  • peteresgate@outlook.com
    1.10.2019 11:48:55

    That's great to hear Stefan.  Bfexplorer truly is the best- no other software can do what Bfexplorer can.  For my non programming brain I wonder "how", but with your knowledge you always "know".  I very much look forward to the final solution :)

  • peteresgate@outlook.com
    4.10.2019 4:07:02

    Please see Your Code for Part 2 (with some additions and comments)  There is 1 thing that I cannot see in the code (line 187 - 192), and that is when a horse has improved in position, then I don't want it in mySelection.  I only want to lay it if it is in the same position or has worsened in position, (and not in top 3 which is coded on line 194).  Is it somewhere that I cannot see?

    https://github.com/PeterEsgate/BfexplorerTestBots/blob/master/HorseRacingBotTrigger2-3.fsx

  • Stefan
    4.10.2019 16:04:07

    I see you are quick learner, as you managed to learn match expression, my congratulation.

    For allowed selections it is initialized mySelections that is list of MySelection objects.

    When race is started setStartData sets start price and position.

    When is time to start your strategy getMySelection function on the line 185 reevaluates set parametes, so odds difference and horse position difference. In your case you use only position difference, and on the line 187 you have got mySelections sorted by PositionDifference.

    My original code take just first selection with minimal position difference, keep in mind that minus values are less than 0.

    If you want to apply different algorithm for selecting a selection from mySortedSelections, then you can simply apply any filter function on this mySortedSelections, or of course sort mySelections by different property, or sortByDescending.

    You can change the line 208 according to your selection algorithm.

  • peteresgate@outlook.com
    5.10.2019 4:51:26

    Is there a way to

    match getMySelection() with
    | Some mySortedSelection -> (where mySortedSelection is a list?) 

    instead of having a lot of

     match getMySelection() with
    | Some mySelection1 ->

     match getMySelection() with
    | Some mySelection2 ->

     match getMySelection() with
    | Some mySelection3 ->........................etc

     

  • peteresgate@outlook.com
    5.10.2019 7:29:57

    Actually, I think I can work it out thanks, but could you please show me how to get trigger to "get" past strategy results.  Thanks

  • Stefan
    5.10.2019 12:13:52

    Just a hint, you really overcomplicate your code. You should separate logic part/s in your code to function/s. For instance you introduced new parameter and named it strategy.

    From your code I can estimate that your intention was to generate allowedSelectionIndexes when the parameter AllowedSelectionIndexes is not entered.

    So you could take this code out from getMySelections function and create a new function that will return just text representation of your strategy number to text representation of allowed selections, so function:

    val strategyToIndexes : int -> string

    That is function signature. Please, maybe you should read this article:

    https://fsharpforfunandprofit.com/posts/how-types-work-with-functions/

    So simply said everything in F# is function, and returns some value, if nothing is return it is called unit.

    Then even “if else then”, is function and returns value, and it is clear that all blocks of if evaluation must return the same value, but I think you already noticed that, but your coding style did not change because you repeatedly type too much code.

    Ok, that is not a problem for now because bot trigger code will work anyway, but on the other hand your code would be shorter, maybe even more than 50% of current code.

    I do not know why would you need to evaluate what is retuned by getMySelection()  function, that other comment with match expression.

    Just hover with your mouse over getMySelection and read tooltip VS shows, it shows function signature:

    val : getMySelection : (unit -> Selection option)

    So what does it mean?

    getMySelection is function taking no input value/s (unit) and returning option type of Selection

    Option can be Some value or None, so in this context getMySelection returns Some selection on which your want to trigger your action bot. If no qualified selection is evaluated by your trigger code than it returns None.

    When starting to build/develop a new trigger you can create functions so they all describe your entire algorithm, and in Execute function then you should see/read your algorithm just by reading function names, all functions could be declared as empty code, just with correct function signature, so in the first stage of development you would just express your trigger algorithm by pure functions, then later start to implement the code to all functions and when necessary adds new ones.

    As your bot trigger cannot be executed in one market update call, it is good idea to introduce trigger status value like I did with TriggerStatus (discriminated union type):

    https://fsharpforfunandprofit.com/posts/discriminated-unions/

    It is clear that I created domain of that discriminated union in the domain of your horse racing trigger, therefore you can see that I named one status:  WaitForRaceStart (and I could name it more generally)

    Now you want to add a new status to your trigger, as you want to evaluate previous bet results, the question is where in the status queue you add this new one, and it is up to you.

    I already described necessary code in my previous comment, but here is another version:

    HorseRacingAndPreviousResultsBotTrigger.fsx