User Comments

  • 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?

  • Stefan
    9.10.2019 9:52:19

    Programming languages use different syntax, and of course set of types. In F# float is C# double, and as F# is .net language you have got access to anything from .net framework.

  • Stefan
    8.10.2019 15:51:11

    I do not know why you need two other lists to make your new list having only selections with profit and unmatched lay bets.

    Any information you need are in Selection object. I created short console script where you can see how to make different filter functions:


    Basically you should orchestrate bot strategy(ies) execution in your trigger code, so the same way you can query for running bots, and running bot on a selection is still indication that your trading session, or bet placing is not yet finished.

    Another hint, please really use Visual Studio InteliSense support, as typing . (dot) in the name of object variable gives you all properties or methods you can use on the object. I mean what I created you could figure out as well.

  • Stefan
    7.10.2019 10:48:02

    For the property BetType, the BetType is not string/text value. It is enumeration value, so you must assign BetType.Back or BetType.Lay

    For “Place Bet and Close Selection Bet Position Bot” you have got OpenBetPosition or CloseBetPosition properties, so exact path to particular parameters, in OpenBetPosition is:



    And for “Place Bet” bot the parameter names are simple:



    Only you know what action bot you will use, so therefore you must know names of action bot parameters. When you always use just “Place Bet” bot then you do not have to code it naming convention of parameters, but when your bot trigger can execute trading bots, then introduce to your bot trigger parameters for instance parameter: “IsTradingActionBot” and when you set it to True, you must add OpenBetPosition. or CloseBetPosition. prefix to the parameter names you want to change. 

    There are of course different ways to create bot instance and execute them, please have a look at here: ScalpingTradingStrategyBot.fsx

    Or just investigate all options for TriggerResult discriminated union type, there are 10 different options for TriggerResult.Execute..

    You are using the option to edit parameters of set action bot, so what you set in “BotName” parameter of "Execute Trigger Bot".

  • 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:

    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):

    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:


  • 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.

  • Stefan
    2.10.2019 14:04:20

    For me it is really hard to help you with understanding a programming language, because I know many programming languages, and all is understandable for me.

    I can read or start programming with any programming language just from seeing code samples or tutorials in minutes.

    I would suggest reading the following post, or entire web site:

    On the Internet you can find a lot of videos, tutorials, books, and so on. As I mentioned if you have problems to understand F#, and C# is better alternative then you can switch your code to C# or Visual Basic.

  • Stefan
    2.10.2019 12:21:02

    Peter, I will really suggest you to read error messages when you build your bot trigger.

    First error reports:

    This function takes too many arguments, or is used in a context where a function is not expected.

    It is where you put HorseRacingBotTrigger2, so constructor of your bot trigger, constructor is function as input to the function:

    MyStrategyOperations.GetMyStrategyResults expects as input strategy name, so string/text value.

    Ok, when you correct input value, so incorrect context you type:

    let myStrategyResults = MyStrategyOperations.GetMyStrategyResults(botName)

    Then there is no other error in this line, but you must understand what is actually returned by GetMyStrategyResults, and how you will use it.

    When you hover your mouse over GetMyStrategyResults, tooltip shows you what you will get, and this data must be used in correct context as well.

    Please read about programming at least couple pages of text, because code is not just text.

    It is like you misspell a sentence the way no one is able to understand what you wanted to say.

    You can develop your bot trigger in C# programming language as well, but as script you can use only code written in F#.

    I can prepare simple bot trigger working with previous results, but I do not think you will manage to use such code yourself.

  • Stefan
    2.10.2019 10:21:05

    You cannot use console script code in your bot trigger code. It was created in other context and for other purpose.

    If you would read error message in Visual Studio or Visual Code (I do not know which IDE you are using.), then errors would suggest problems in your code.

    Please, just read what IDE suggests.

  • Stefan
    1.10.2019 14:20:51

    We have got your strategy for horse racing programmed as bot trigger:

    Bot Trigger Building Part 2

    Bot trigger code is executed by bot called: “Execute Trigger Bot”, and trigger executes the action bot, so bot strategy that places bets or starts trading session. In my test I used: “Lay trade 4 ticks”. I named this strategy: “Horse Racing Bot Trigger”.

    So you have got your strategy that can be executed manually from My Strategies /Bots to Execute, on the market you open in Bet Event view, just selecting your strategy “Horse Racing Bot Trigger” and clicking on the Execute toolbar button.

    If you want to execute your strategy automatically on all races, then you can use “Bot Executor” tool.

    Bfexplorer app offer more general purpose bot strategies, one them is bot strategy named: “Execute Till Target Profit”, and that is what you need, to stop the execution of your strategy when it is executed automatically, when target profit or loss is reached. Again, the bot uses action bot to be executed, set by parameter BotName, in our case we want to execute: “Horse Racing Bot Trigger” and that is all. Just name your strategy (I named it: “My Horse Racing Strategy”) and execute it at set time relative to the race time (market start time).

    When programming your strategy using Bfexplorer BOT SDK, you have got access to all bfexplorer generated data with public interface, so you can access your betting results, or create your own version of “Execute Till Target Profit”.

    For instance Bfexplorer Console, the tool executing a script code to automate bfexplorer UI interaction, or querying data. The similar script can be programmed to read your strategy results and process data.

    For instance here is script opening Match Odds and Over/Under 2.5 Goals markets that met required parameters:


  • 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.

  • 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.

  • Stefan
    1.10.2019 9:21:15

    Ok, it seems you managed to understand the concept of F# programming.

    On the other hand I see you have actually no understanding of betting terminology, as book value is not calculated as you did in your code. The book value in betting is sum of selection’s probabilities.

    Here is my bot trigger code for part 2: HorseRacingBotTrigger2.fs

  • Stefan
    30.9.2019 16:21:59

    Here is my first test that actually triggered some trading session. When testing it is really important how you set all trigger parameters, for testing it is good to set them without limits, so not parameters are tested but code

    I set the fallowing parameters as default ones:

    allowedSelectionIndexes: 1,2,3,4,5,6

    timeToStart: 40.0

    favouritesPrice: 50.0

    When the race started, bot trigger saved position of allowed horses. When timeToStart expired, all allowed horses were evaluated again

    positionDifference <- startPosition – position

    So trigger selected Bianca Minola as nominated selection on which Bot Trigger started lay/back trading session for 4 ticks of profit.

  • Stefan
    30.9.2019 9:56:56

    Peter, I do not want to patronize you, but I have got very simple question?

    Are you satisfied with what you did?

    Why did I ask?

    Because any written source code must be formatted to be readable by other programmers.

    Yes, some programming languages that use for instance { } to separate block of code, could be stripped to one line and compiler successfully build such code, but not F# where code block must be formatted by text/code indentation and you cannot used tabs:

    I mentioned that, because during weekend you posted video showing you edited bot trigger in Notepad text editor. So anyone who would like to use your code you posted in your comment, must copy and paste your text, reformat it correctly, and then will find out that your code does not do what you claim you did.

    So you waste maybe 10 minutes or more, to someone who wants to test your code. English is foreign language for me so is very hard for me to find politically correct words for your behavior.

    Please, install either Visual Code, like I show here:

    Betfair Bot Programming for Non-Developers

    Or Visual Studio Community version:

    Bfexplorer - Betfair BOT SDK

    Both IDE (Integrated Developer Environment) applications are free, unlike Microsoft Excel other betfair app use, where you must buy licenses of Microsoft Excel. Using Bfexplorer BOT SDK all applications or tools helping you to create bot trigger are for free.

    Why is using right programs/applications important when developing/writing code?

    Because like text editors with spellchecking, such IDE checks your code when writing, so any mistake in misspelling anything in code is reported. Visual Studio, or Visual Studio code offer you as well, so called IntelliSense/IntelliCode technology when writing code, so helping you to write the code:

    And finally why did I ask you to make some changes in the code?

    To force you learn something, because bot trigger code in other parts of our tutorial will be more difficult.

    I know you are not software developer, but in part 1 the source code is really readable even by non programmer, it contains plain English words like if, then, else, match, let, try, with, and some words you would maybe need to think about, like open, type, interface, member and map

    Please, when you want to use source code, and want to share it with others, do them favor and share it on through Github Gist, like I do:

    Again, you can register on for free. Or just use any of other code sharing services on the Internet:

  • Stefan
    28.9.2019 0:46:54

    Ok, but you did not specify that you want to check horse's positions in two different times. My first implementation was that bot waits till market is turned at in-play, then saves information about all allowed selections, so horse's positions is saved as well.

    At set time in race, bot checks your conditions, so favourites must be traded at that moment of checking under set price/odds.

    Then allowed selections are sorted by position change difference, so biggest position change is the first one, if this selection is not among the first three favourites, it is nominated as the selection your strategy will be executed on.

    The bot trigger again similar like I explained to you in the part 3, does not have to know anything about your criteria for entry point, so if you allow starting lay/back trading session only when the selection/horse is traded from 10.0 to 20.0, then you can simply set that to Entry Criteria for this lay trading bot.

    Now think a little bit. I hope you already know that Entry Criteria could be evaluated just once, or could be evaluated till all set Entry Criteria are met. This feature gives you two different options for your bot placing a lay bet.

    If you think more, then you will find that bfexplorer offers more bots placing a bet, or starting trading session, namely:

    Place Bet

    Be the First in Queue

    Fill or Kill

    Place Bet and Close Selection Bet Position

    Scratch Trading

    This gives you really big flexibility for different ways your bet is placed on the market selection, and closes your bet position for loss when needed.

    Of course not all of above bot strategies to place a bet are suitable for in-play markets where odds changes so rapidly as on the horse racing, therefore I would suggest to use:

    Place Bet and Close Selection Bet Position

    But of course you can test them all, or other combinations for instance:

    Place Bet, and Trailing Stop Loss

    What is very good news for you is that bot trigger code does not have to implement anything to place a bet and manage its status, so you will get simpler trigger code.

    I really cannot imagine how people could manage such strategies just in Excel spreadsheets, so traders using Bet Angel, Cymatic or Gruss software. I think they cannot run such strategies, am I right?

    Your tutorial in the part 1 is ready, I will post bot trigger code for the part 2, but first test your bot trigger for part 1, and as the simple coding exercise, change the bot trigger code to report not only horse name, but the last traded price as well.

    Here is the hint:

  • Stefan
    27.9.2019 18:44:20

    How is evaluated “…our selection has dropped in position...”?

  • Stefan
    27.9.2019 17:55:07

    Peter, you do not need to program a trigger or anything for this feature, as your lay trade can be started by bot strategy: “Place Bet and Close Selection Bet Position”, and set your Profit/Loss target as required. So in your case you want to close your bet position, so by your words:

    “… so that if it looks like my trade is not going good, I'd like to limit my losses …”

    You can set Loss parameter, either by (ProfitLossType parameter) Ticks, Percentage, or exact Money value.  As the Profit parameter is required one, (Loss is not, when you set it to 0, your position is not closed for Loss) you must set it to unrealistic value.

    If you want to hedge your bet position, leave HedgingEnabled checked (set to True). When hedge the stake is calculated, I hope that you understand that, other software vendors call this procedure “green up”. Well, in this case I really do not understand your English, as no one is saying about “red up” ;-)