Eric’s Bot implementation

In my previous article Eric’s LookUpBot bot implementation I described how to implement the LookUpBot that can be used with the Trade Opportunity Lookup service. In this article I will explain how to create the Bot that can be used with the Bot Executor. I will use the same project specification so you can compare both approaches.

using System;
using BeloSoft.Betfair.Data;
using BeloSoft.Betfair.Data.Betting;
using BeloSoft.Betfair.Data.Statistics;
using BeloSoft.Betfair.Trading;

namespace Bfexplorer.Scripting
{
  public class EricBot : Bot
  {
    // Const
    private const byte SolutionId = 100;
    private const string SolutionName = "Eric Horse Racing Solution";
    private static string[] NotAllowedMarkets = { "Hcap", "Nursery" };

    // Data
    private MySolutionMarkets mySolutionMarkets;
    private RunnersSortedCollection runnersSortedCollection;

    public EricBot(IBetfairService betfairService, MonitoredMarket monitoredMarket, Runner runner)
      : base(betfairService, monitoredMarket, runner)
    {
      mySolutionMarkets = betfairService.RegisterMySolution(SolutionId, SolutionName);

      runnersSortedCollection = new RunnersSortedCollection();
      runnersSortedCollection.SortByType = RunnersSortedCollection.SortType.ByLastPriceMatched;
      runnersSortedCollection.Initialize(monitoredMarket);
    }

    public override void DoYourJob()
    {
      base.DoYourJob();

      if (GetIsMyMarket())
      {
        bool stopBetting;

        if (GetCanRunThisSolution(out stopBetting))
        {
          BetType betType;
          Runner myRunner = GetRunnerToBet(out betType);

          if (myRunner != null)
          {
            SetupMyBot(myRunner, betType);
          }

          Stop();
        }
        else if (stopBetting)
        {
          Stop();
        }
      }
      else
      {
        Stop();
      }
    }

    private bool GetIsMyMarket()
    {
      string marketName = monitoredMarket.MarketInfo.Market.Name;

      foreach (string notAllowedMarket in NotAllowedMarkets)
      {
        if (marketName.Contains(notAllowedMarket))
        {
          return false;
        }
      }

      return true;
    }

    private bool GetCanRunThisSolution(out bool stopBetting)
    {
      stopBetting = false;

      if (mySolutionMarkets.ReadyForNextBet)
      {
        int total;
        bool isWinningStreak;

        mySolutionMarkets.GetBettingStreak(out total, out isWinningStreak);

        if (!isWinningStreak && total >= RunnerProperty.StopLossOnPercentageLiability)
        {
          stopBetting = true;
        }
        else
        {
          return true;
        }
      }

      return false;
    }

    private Runner GetRunnerToBet(out BetType betType)
    {
      betType = BetType.Lay;

      runnersSortedCollection.Sort();

      foreach (Runner runner in runnersSortedCollection.Data)
      {
        BetPrice betPrice = runner.BestPriceToBack;

        if (betPrice != null)
        {
          double odds = betPrice.Price;

          if (odds < RunnerProperty.Odds)
          {
            return runner;
          }
          else if (odds >= RunnerProperty.MinimalOdds && odds <= RunnerProperty.MaximalOdds)
          {
            betType = BetType.Back;

            return runner;
          }
        }
        else
        {
          break;
        }
      }

      return null;
    }

    private void SetupMyBot(Runner myRunner, BetType betType)
    {
      RunnerProperty runnerProperty = myRunner.RunnerProperty;

      runnerProperty.BotType = BotType.PlaceBet;
      runnerProperty.BetType = betType;
      runnerProperty.Stake = RunnerProperty.Stake;
      runnerProperty.StakeIsMyLiability = betType == BetType.Lay;
      runnerProperty.MinimalOdds = betType == BetType.Back ? RunnerProperty.MinimalOdds : OddsRange.MinOdds;
      runnerProperty.MaximalOdds = betType == BetType.Back ? RunnerProperty.MaximalOdds : RunnerProperty.Odds;
      runnerProperty.AllowPlacingBetInPlay = false;

      betfairService.StartMonitorThisMarket(monitoredMarket);
      betfairService.AddMarketToMoneyManagement(SolutionId, monitoredMarket);
      betfairService.StartBot(monitoredMarket, myRunner.Id);
    }
  }
}

Implementation details

This type of bot when used with the Bot Executor is executed manually on a selected market and a selection. You can also run this bot using the Selection Property setting the MyBot and all bot’s parameters on the selection and then starting the bot by clicking on the menu Market/Start Bot.

The bot runs on the market selection and any time the market data are refreshed the bot’s DoYourJob method is executed. If there are no market data changes then the bot is executed each 5 seconds in the idle time. Only one bot can run on a selection, but you can run bots on each market selection.

The bot can directly access the runner property parameters all market data and actually do anything.

DoYourJob

The method DoYourJob implements the algorithm of our bot, checking if the evaluated market is allowed market (GetIsMyMarket) otherwise stopping the bot execution. If the betting is allowed (GetCanRunThisSolution) the bot makes its selection (GetRunnerToBet) and places the bet (SetupMyBot).

public override void DoYourJob()
{
  base.DoYourJob();

  if (GetIsMyMarket())
  {
    bool stopBetting;

    if (GetCanRunThisSolution(out stopBetting))
    {
      BetType betType;
      Runner myRunner = GetRunnerToBet(out betType);

      if (myRunner != null)
      {
        SetupMyBot(myRunner, betType);
      }

      Stop();
    }
    else if (stopBetting)
    {
      Stop();
    }
  }
  else
  {
    Stop();
  }
}

GetIsMyMarket

If the market name contains not allowed text false is returned so the market is not evaluated by the bot, otherwise returns true. You can change or add not allowed text in the market name in the array:

  • private static string[] NotAllowedMarkets = { "Hcap", "Nursery" };
private bool GetIsMyMarket()
{
  string marketName = monitoredMarket.MarketInfo.Market.Name;

  foreach (string notAllowedMarket in NotAllowedMarkets)
  {
    if (marketName.Contains(notAllowedMarket))
    {
      return false;
    }
  }

  return true;
}

GetCanRunThisSolution

As our betting solution uses stop loss the bot have to keep track for results of previous betting. The money management feature is implemented by bfexplorer infrastructure, so all you need is just register our solution with the Money Management System.

If the result of previous betting is not known yet the bot will wait, when the result is know it checks if our losing streak is more or equal to the preset losing streak. You can change this parameter with this runner property parameter:

  • StopLossOnPercentageLiability (StopAtLosingStreak)
private bool GetCanRunThisSolution(out bool stopBetting)
{
  stopBetting = false;

  if (mySolutionMarkets.ReadyForNextBet)
  {
    int total;
    bool isWinningStreak;

    mySolutionMarkets.GetBettingStreak(out total, out isWinningStreak);

    if (!isWinningStreak && total >= RunnerProperty.StopLossOnPercentageLiability)
    {
      stopBetting = true;
    }
    else
    {
      return true;
    }
  }

  return false;
}

GetRunnerToBet

The bot selection algorithm is to lay horse if its odds is lower the preset odds and back horse if its odds range is in preset range. You can change these parameters:

  • MinimalOdds (MinOddsToBack)
  • MaximalOdds (MaxOddsToBack)
  • Odds (MaxOddsToLay)
private Runner GetRunnerToBet(out BetType betType)
{
  betType = BetType.Lay;

  runnersSortedCollection.Sort();

  foreach (Runner runner in runnersSortedCollection.Data)
  {
    BetPrice betPrice = runner.BestPriceToBack;

    if (betPrice != null)
    {
      double odds = betPrice.Price;

      if (odds < RunnerProperty.Odds)
      {
        return runner;
      }
      else if (odds >= RunnerProperty.MinimalOdds && odds <= RunnerProperty.MaximalOdds)
      {
        betType = BetType.Back;

        return runner;
      }
    }
    else
    {
      break;
    }
  }

  return null;
}

SetupMyBot

After the bot selects its qualified horse for betting the bet have to be placed on this horse. Actually the bet is not placed by this Bot but instead the PlaceBet bot is setup to do it. Our bot just setups the PlaceBet bot parameters, adds the market into the Money Management System and finally starts the PlaceBet bot execution. You can change the stake with this parameter:

  • Stake
private void SetupMyBot(Runner myRunner, BetType betType)
{
  RunnerProperty runnerProperty = myRunner.RunnerProperty;

  runnerProperty.BotType = BotType.PlaceBet;
  runnerProperty.BetType = betType;
  runnerProperty.Stake = RunnerProperty.Stake;
  runnerProperty.StakeIsMyLiability = betType == BetType.Lay;
  runnerProperty.MinimalOdds = betType == BetType.Back ? RunnerProperty.MinimalOdds : OddsRange.MinOdds;
  runnerProperty.MaximalOdds = betType == BetType.Back ? RunnerProperty.MaximalOdds : RunnerProperty.Odds;
  runnerProperty.AllowPlacingBetInPlay = false;

  betfairService.AddMarketToMoneyManagement(SolutionId, monitoredMarket);
  betfairService.StartBot(monitoredMarket, myRunner.Id);
}

How to run the bot

You can run this bot with the Bot Executor or with the Trade Opportunity Lookup Service when setting the bot criteria for this bot. Your bot full class name is:

  • Bfexplorer.Scripting.EricBot

The bot parameters you can set are following:

  • MinimalOdds (MinOddsToBack)
  • MaximalOdds (MaxOddsToBack)
  • Odds (MaxOddsToLay)
  • Stake
  • StakeIsMyLiability
  • AtInPlayCancelBet
  • StopLossOnPercentageLiability (StopAtLosingStreak)

Unlike the LookUpBot version this Bot version can run with the Bot Executor and you can parameterized the Bot creating different settings with the Bot Criteria Editor. You can download the source code here and the bot criteria settings to import into the Bot Executor here.

Conclusion

Well, you can see that writing a bot is not so complicated, mainly when you use the bfexplorer pro infrastructure. What you will implement is just base algorithm of your bot, the market monitoring, bet operations, money management system and bot execution service that all is prepared for you to use.

Happy bot coding!

Comments (1)

  1. EricEllwood Says:
    Sunday, August 24, 2008

    EricBot : Bot

    In this Bot Executor version I like the possibility to change certain parameters in the BotExecutor editor allowing experinemtation with various settings.I have found this to be very useful in other bots when used in conjuction with Bfexplorer "Practice Mode"..without risking any cash in the process. Just these two articles from Stefan have given me great encouragement.

Do you want to comment this article? Sign up here or login.