{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# GRUSS BETTING ASSISTANT COM INTERFACE - TEST PLATFORM"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### This notebook is used to test the methods in the BettingAssistant python file."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Install required packages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# The followning package is required. This need only be installed once.\n",
    "\n",
    "#!pip3 install pythonnet"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Import the BettingAssistant COM Interace python module\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# It is important that this notebook is in the same folder as the BettingAssistant python module.\n",
    "import pandas as pd\n",
    "import clr\n",
    "import BettingAssistant\n",
    "from datetime import datetime\n",
    "import time # Optional. Sleep is used below to delay the execution of some BettingAssistant functions.\n",
    "import psutil # Used to confirm that Betting Assistant is running "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Betting Assistant must be running"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def is_app_running(app_name):\n",
    "    # Iterate through all running processes\n",
    "    for process in psutil.process_iter(['name']):\n",
    "        # Check if the process name matches the app name\n",
    "        if process.info['name'] and app_name.lower() in process.info['name'].lower():\n",
    "            return True\n",
    "    return False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "if not is_app_running(\"Betting Assistant.exe\"):\n",
    "    raise SystemExit(\"Stopping execution because Betting Assistant is not running.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Create an instance of the BettingAssistant COM Interface class"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<module 'BettingAssistant' from 'c:\\\\Users\\\\arthu\\\\Dropbox\\\\Arthurs Code\\\\Projects\\\\Gruss Class (Python)\\\\BettingAssistant.py'>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import importlib\n",
    "importlib.reload(BettingAssistant)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "myBA = BettingAssistant.BAHandler(\"c:/Program Files (x86)/Betting Assistant/BettingAssistantCom.dll\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### BettingAssistant ComClass Properties"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The BA Version is 1.3.2.6g\n",
      "The Commission Rate is 2\n",
      "includeNonRunners was set to False\n",
      "includeNonRunners is now set to True\n",
      "keepBetType was set to 0\n",
      "keepBetType is now set to 1\n",
      "The Market Id is 233192933\n",
      "The Market Name is Newbury 20th Sep - 13:25 6f Mdn Stks\n",
      "refreshRate was set to 1.0\n",
      "refreshRate is now set to 0.2\n",
      "The Start Time is 20/09/2024 13:25:00\n",
      "The tabIndex is 0\n"
     ]
    }
   ],
   "source": [
    "# BA Version\n",
    "print(f'The BA Version is {myBA.ba_Version()}')\n",
    "\n",
    "#  Commission Rate\n",
    "print(f'The Commission Rate is {myBA.Commission_Rate()}')\n",
    "\n",
    "# includeNonRunners\n",
    "print(f'includeNonRunners was set to {myBA.get_Include_NonRunners()}')\n",
    "if myBA.get_Include_NonRunners():\n",
    "    myBA.set_Include_NonRunners(False)\n",
    "else:\n",
    "    myBA.set_Include_NonRunners(True)\n",
    "print(f'includeNonRunners is now set to {myBA.get_Include_NonRunners()}')\n",
    "\n",
    "# keepBetType\n",
    "print(f'keepBetType was set to {myBA.get_Keep_Bet_Type()}')\n",
    "if myBA.get_Keep_Bet_Type() == 0:\n",
    "    myBA.set_Keep_Bet_Type(1)\n",
    "elif myBA.get_Keep_Bet_Type() == 1:\n",
    "    myBA.set_Keep_Bet_Type(2)\n",
    "else:\n",
    "    myBA.set_Keep_Bet_Type(0)\n",
    "print(f'keepBetType is now set to {myBA.get_Keep_Bet_Type()}')\n",
    "\n",
    "# marketId (There must be an open market on the first tab for this snippet to work, setting the tab index comes later)\n",
    "print(f'The Market Id is {myBA.Market_Id()}')\n",
    "\n",
    "# marketName (There must be an open market on the first tab for this snippet to work, setting the tab index comes later)\n",
    "print(f'The Market Name is {myBA.Market_Name()}')\n",
    "\n",
    "# refreshRate\n",
    "print(f'refreshRate was set to {myBA.get_Refresh_Rate()}')\n",
    "if myBA.get_Refresh_Rate() == 1:\n",
    "    myBA.set_Refresh_Rate(0.2)\n",
    "else:\n",
    "    myBA.set_Refresh_Rate(1)\n",
    "print(f'refreshRate is now set to {myBA.get_Refresh_Rate()}')\n",
    "\n",
    "# startTime (There must be an OPEN market on the first tab for this snippet to work, setting the tab index comes later)\n",
    "print(f'The Start Time is {myBA.Start_Time()}')\n",
    "\n",
    "# tabIndex\n",
    "print(f'The tabIndex is {myBA.Tab_Index()}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### BettingAssistant ComClass Events"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "TO DO"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### BettingAssistant ComClass Functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The number of Tab Pages after addition is 2\n",
      "The number of Tab Pages after deletion is 1\n"
     ]
    }
   ],
   "source": [
    "# addTabPage\n",
    "print(f'The number of Tab Pages after addition is {myBA.add_Tab_Page()}')\n",
    "\n",
    "# deleteTabPage\n",
    "print(f'The number of Tab Pages after deletion is {myBA.delete_Tab_Page(1)}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1. Bet reference is 361643293183\n",
      "2. Bet reference is 361643293348\n",
      "3. Bet reference is 361643293541\n",
      "4. Bet reference is 361643293663\n",
      "5. Bet reference is 361643293762\n",
      "6. Bet reference is 361643293862\n",
      "7. Bet reference is 361643293996\n",
      "8. Bet reference is 361643294204\n",
      "9. Bet reference is 361643294413\n",
      "10. Bet reference is 361643294497\n",
      "11. Bet reference is 361643294565\n",
      "12. Bet reference is 361643294684\n",
      "13. Bet reference is 361643294795\n",
      "All unmatched bets cancelled.\n"
     ]
    }
   ],
   "source": [
    "# backField\n",
    "i = 1\n",
    "response = myBA.back_Field(1000, 0.10)\n",
    "for resp in response:\n",
    "    print(f'{i}. Bet reference is {resp}')\n",
    "    i += 1\n",
    "\n",
    "time.sleep(1)\n",
    "\n",
    "# cancelAllBets\n",
    "response = myBA.cancel_All_Bets()\n",
    "if response == '':\n",
    "    print('All unmatched bets cancelled.')\n",
    "else:\n",
    "    print(f'Error message from cancel_All_Bets: {response}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Bet placed. Reference: 361643295475\n",
      "cancel_Bet cancelled 0.1 of unmatched staked for bet reference 361643295475\n",
      "Bet placed. Reference: 361643296540\n",
      "The market Id is 233192933\n",
      "cancel_Bet with event Id  cancelled 0.1 of unmatched staked for bet reference 361643296540\n"
     ]
    }
   ],
   "source": [
    "# cancelBet\n",
    "# Note: use the market Id as the event Id if applicable\n",
    "# response = myBA.cancelBet('<your bet reference>', <optional event id>)\n",
    "\n",
    "# Add a bet so there is something to cancel\n",
    "bet_Ref = myBA.place_Bet(0, 'B', 1000, 0.10, True, 'Anything you want!', -1, keepBetType=0)\n",
    "print(f'Bet placed. Reference: {bet_Ref}')\n",
    "\n",
    "time.sleep(1)\n",
    "\n",
    "# Example without event Id\n",
    "response = myBA.cancel_Bet(bet_Ref)\n",
    "print(f'cancel_Bet cancelled {response} of unmatched staked for bet reference {bet_Ref}')\n",
    "\n",
    "time.sleep(1)\n",
    "\n",
    "# Example using an event Id\n",
    "# Place a bet then use the get_Bets function to return the market Id.\n",
    "bet_Ref = myBA.place_Bet(0, 'B', 1000, 0.10, True, 'Anything you want!', -1, keepBetType=0)\n",
    "print(f'Bet placed. Reference: {bet_Ref}')\n",
    "\n",
    "time.sleep(1)\n",
    "\n",
    "response = myBA.get_Bets()\n",
    "bet = response[0]\n",
    "mid = bet.marketId\n",
    "print(f'The market Id is {mid}')\n",
    "\n",
    "time.sleep(1)\n",
    "\n",
    "response = myBA.cancel_Bet(bet_Ref, mid)\n",
    "print(f'cancel_Bet with event Id  cancelled {response} of unmatched staked for bet reference {bet_Ref}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Selection: Haazeez; actualBsp: 0.0;  totalBspBackMatchedAmount: 0.0;  totalBspLiabilityMatchedAmount: 0.0;  tradedVolumes Odds: 3.1; tradedVolumes totalBspBackMatchedAmount: 0.0;  tradedVolumes totalBspLiabilityMatchedAmount: 0.0;  tradedVolumes totalMatchedAmount: 14.7\n"
     ]
    }
   ],
   "source": [
    "# getAllTradedVolume\n",
    "response = myBA.get_All_Traded_Volume(True)\n",
    "\n",
    "# Using the first element in each array rather than loop through all the elements\n",
    "resp = response[0]\n",
    "trade = resp.tradedVolumes[0]\n",
    "print(f'Selection: {resp.selection}; actualBsp: {resp.actualBsp}; ', \n",
    "    f'totalBspBackMatchedAmount: {resp.totalBspBackMatchedAmount}; ', \n",
    "    f'totalBspLiabilityMatchedAmount: {resp.totalBspLiabilityMatchedAmount}; ',\n",
    "    f'tradedVolumes Odds: {trade.odds}; tradedVolumes totalBspBackMatchedAmount: {trade.totalBspBackMatchedAmount}; ',\n",
    "    f'tradedVolumes totalBspLiabilityMatchedAmount: {trade.totalBspLiabilityMatchedAmount}; ', \n",
    "    f'tradedVolumes totalMatchedAmount: {trade.totalMatchedAmount}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "# getBalance\n",
    "response = myBA.get_Balance(1)\n",
    "# For my security, I am not outputing my Betfair balance! \n",
    "#print(f'availBalance: {response.availBalance}; balance: {response.balance}; exposure: {response.exposure}.')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Bet placed. Reference: 361643298379\n",
      "\n",
      "Refence: 361643298379; avgPrice: 0.0; betStatus: U; betType: B; \n",
      "matchedDate: 01/01/0001 00:00:00; matchedSize: 0.0; price: 1000.0; remainingSize: 0.1;\n",
      "requestedSize: 0.1; selectionId: 69400780; selectionName: Haazeez; \n",
      "marketId: 233192933; betCategoryType: E; errorCode: OK;  ProfitAndLoss: 0.0;\n",
      "\n",
      "cancel_Bet cancelled 0.1 of unmatched staked for bet reference 361643298379\n"
     ]
    }
   ],
   "source": [
    "# getBet\n",
    "\n",
    "# Place a bet so that there is an object to report on.\n",
    "bet_Ref = myBA.place_Bet(0, 'B', 1000, 0.10, True, 'Anything you want!', -1, keepBetType=0)\n",
    "print(f'Bet placed. Reference: {bet_Ref}\\n')\n",
    "\n",
    "time.sleep(1)\n",
    "\n",
    "resp = myBA.get_Bet(bet_Ref, 1)\n",
    "print(f'Refence: {resp.ref}; avgPrice: {resp.avgPrice}; betStatus: {resp.betStatus}; betType: {resp.betType}; ') \n",
    "print(f'matchedDate: {resp.matchedDate}; matchedSize: {resp.matchedSize}; price: {resp.price}; remainingSize: {resp.remainingSize};')\n",
    "print(f'requestedSize: {resp.requestedSize}; selectionId: {resp.selectionId}; selectionName: {resp.selectionName}; ')\n",
    "print(f'marketId: {resp.marketId}; betCategoryType: {resp.betCategoryType}; errorCode: {resp.errorCode}; ' ,\n",
    "    f'ProfitAndLoss: {resp.profitAndLoss};')\n",
    "\n",
    "time.sleep(1)\n",
    "\n",
    "response = myBA.cancel_Bet(bet_Ref)\n",
    "print(f'\\ncancel_Bet cancelled {response} of unmatched staked for bet reference {bet_Ref}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Bet placed. Reference: 361643300815\n",
      "Bet placed. Reference: 361643300870\n",
      "\n",
      "1. Selection: Shameful; Ref: 361643300870; betDate: 20/09/2024 05:28:22; betType: B; Stake: 0.1; Odds: 1000.0; Matched: False; SelectionId: 4804060; marketId: 233192933.\n",
      "2. Selection: Haazeez; Ref: 361643300815; betDate: 20/09/2024 05:28:22; betType: B; Stake: 0.1; Odds: 1000.0; Matched: False; SelectionId: 69400780; marketId: 233192933.\n",
      "\n",
      "All unmatched bets cancelled.\n"
     ]
    }
   ],
   "source": [
    "# getBets\n",
    "\n",
    "# Place bets so that there are objects to report on.\n",
    "bet_Ref = myBA.place_Bet(0, 'B', 1000, 0.10, True, 'Anything you want!', -1, keepBetType=0)\n",
    "print(f'Bet placed. Reference: {bet_Ref}')\n",
    "\n",
    "bet_Ref = myBA.place_Bet(1, 'B', 1000, 0.10, True, 'Anything you want!', -1, keepBetType=0)\n",
    "print(f'Bet placed. Reference: {bet_Ref}\\n')\n",
    "\n",
    "time.sleep(1)\n",
    "\n",
    "response = myBA.get_Bets()\n",
    "i = 1\n",
    "for resp in response:\n",
    "    print(f'{i}. Selection: {resp.selection}; Ref: {resp.ref}; betDate: {resp.betDate}; betType: {resp.betType}; ' \\\n",
    "          f'Stake: {resp.stake}; Odds: {resp.odds}; Matched: {resp.matched}; SelectionId: {resp.selectionId}; ' \\\n",
    "          f'marketId: {resp.marketId}.')\n",
    "    i += 1\n",
    "    \n",
    "# cancelAllBets\n",
    "response = myBA.cancel_All_Bets()\n",
    "if response == '':\n",
    "    print('\\nAll unmatched bets cancelled.')\n",
    "else:\n",
    "    print(f'\\nError message from cancel_All_Bets: {response}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1. Selection: Haazeez; DSLR: 78; \n",
      "2. Selection: Shameful; DSLR: 0; \n",
      "3. Selection: Belgrave; DSLR: 16; \n",
      "4. Selection: Maelstrom; DSLR: 15; \n",
      "5. Selection: Wicket Keeper; DSLR: 0; \n",
      "6. Selection: Juba; DSLR: 15; \n",
      "7. Selection: Iconic Times; DSLR: 0; \n",
      "8. Selection: Antelope; DSLR: 34; \n",
      "9. Selection: Im Workin On It; DSLR: 0; \n",
      "10. Selection: Kodi Fire; DSLR: 16; \n",
      "11. Selection: Medinilla; DSLR: 0; \n",
      "12. Selection: Spirit Lead Me; DSLR: 27; \n",
      "13. Selection: Excellent Echo; DSLR: 48; \n"
     ]
    }
   ],
   "source": [
    "# getDaysSinceLastRun\n",
    "\n",
    "# This function requires the horse's name from the price object.\n",
    "# There must be an OPEN market on the first tab for this snippet to work\n",
    "prices = myBA.get_Prices()\n",
    "i = 1\n",
    "for priceItem in prices:\n",
    "    resp = myBA.get_Days_Since_Last_Run(priceItem.selection)\n",
    "    print(f'{i}. Selection: {priceItem.selection}; DSLR: {resp}; ')\n",
    "    i = i + 1\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "# getEvents"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is a somewhat complicated function as events has several layers. \n",
    "\n",
    "We'll start with a sportsId (see getSports below) but this will only return the event name, for example in horse racing \n",
    "'#1#~Southwell 25th May~'\n",
    "\n",
    "We then need to drill down the layers of events until we to events where 'isMarket' is true as this is the object which will accept our bets. We do this by itervatively calling Get_Events\n",
    "\n",
    "At the top level (Index = 0 and the eventId equals a sportsId) Get_Events returns something like this:\n",
    "\n",
    "Index: 0. Name: USA; Id: 1549530393; Start: 01/01/0001 00:00:00;  isMarket: False; Exchange Id: 0; Turn InPlay: ;\n",
    "\n",
    "Index: 0. Name: GB; Id: 1549628216; Start: 01/01/0001 00:00:00;  isMarket: False; Exchange Id: 0; Turn InPlay: ; \n",
    "\n",
    "Index: 0. Name: IRE; Id: 1549628223; Start: 01/01/0001 00:00:00;  isMarket: False; Exchange Id: 0; Turn InPlay: ; \n",
    "\n",
    "Index: 0. Name: NZL; Id: 1548787524; Start: 01/01/0001 00:00:00;  isMarket: False; Exchange Id: 0; Turn InPlay: ;\n",
    "\n",
    "We extract the country identifier at this point.\n",
    "\n",
    "Id gives the eventId for the second call. Here we can filter out events we are not interested in, e.g. I only want UK and IRE racing.\n",
    "\n",
    "For horse racing, the second level (index = 1) returns something like this:\n",
    "\n",
    "Index: 1. Country: GB; Venue:  Name: Salisbury 13th Sep; Id: 33577798; Start: 01/01/0001 00:00:00;  isMarket: False; Exchange Id: 0; Turn InPlay: ; \n",
    "\n",
    "We extract the venue identifier at this point.\n",
    "\n",
    "Index: 2. Country: GB; Venue:  Name: 2 TBP; Id: 232902023; Start: 13/09/2024 19:10:00;  isMarket: True; Exchange Id: 1; Turn InPlay: Y; \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [],
   "source": [
    "def Get_Events(eventId, index = 0, country = '', venue = ''):\n",
    "    today = datetime.today()  # Used to filter events to today's date only.\n",
    "    ev = myBA.Get_Events(eventId)\n",
    "    for e in ev:        \n",
    "        #print(f'Index: {index}. Country: {country}; Venue: {venue} Name: {e.eventName}; Id: {e.eventId}; Start: {e.startTime}; ',\n",
    "        #    f'isMarket: {e.isMarket}; Exchange Id: {e.exchangeId}; Turn InPlay: {e.turnInPlay}; ')\n",
    "        \n",
    "        if not e.isMarket:\n",
    "            if index == 0 and e.eventName != \"GB\" and e.eventName != \"IRE\":\n",
    "                country = ''\n",
    "                continue\n",
    "            elif index == 0 and e.eventName == \"GB\":\n",
    "                Get_Events(e.eventId, 1, 'GB')\n",
    "            elif index == 0 and e.eventName == \"IRE\":\n",
    "                Get_Events(e.eventId, 1, 'IRE')\n",
    "         \n",
    "            if index == 1:\n",
    "                # Parse the event name to extract the venue. Only get today's races though\n",
    "                if e.eventName.find(today.strftime(\"%d\")) > 0 and e.eventName.find(today.strftime(\"%b\")) > 0:\n",
    "                    if e.eventName.find('(US)') > 0 or \\\n",
    "                       e.eventName.find('(AUS)') > 0 or \\\n",
    "                       e.eventName == 'Reverse Forecast':\n",
    "                        continue\n",
    "\n",
    "                    venue = e.eventName.replace('#1#~', '')\n",
    "                    p = venue.find(today.strftime(\"%d\"))\n",
    "                    venue = venue[:p].strip()\n",
    "                else:\n",
    "                    continue\n",
    "            \n",
    "            # Get the next layer down for this event until we get to the tradeable markets\n",
    "            Get_Events(e.eventId, index + 1, country, venue)\n",
    "        else: # isMarket\n",
    "            if e.turnInPlay == 'Y':\n",
    "                # There are many markets I have no interest in, you may want to adjust this selection\n",
    "                if not e.eventName == 'Each Way' and \\\n",
    "                   e.eventName != 'To Be Placed' and \\\n",
    "                   e.eventName != 'Reverse FC' and \\\n",
    "                   e.eventName.find('Match Betting') == -1 and \\\n",
    "                   e.eventName.find('Without ') == -1 and \\\n",
    "                   e.eventName.find('TBP') == -1:\n",
    "                    df_events.loc[len(df_events.index)] = [country, venue, e.eventName, e.eventId, e.startTime]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   Country     Venue         Name         Id            StartTime\n",
      "0       GB  Beverley  5f Nov Stks  233379806  24/09/2024 14:45:00\n",
      "1       GB  Beverley  1m Nov Stks  233379799  24/09/2024 14:10:00\n",
      "2       GB  Beverley      5f Hcap  233379816  24/09/2024 15:55:00\n",
      "3       GB  Beverley      5f Stks  233379811  24/09/2024 15:20:00\n",
      "4       GB  Beverley    1m2f Hcap  233379788  24/09/2024 13:40:00\n",
      "..     ...       ...          ...        ...                  ...\n",
      "75          Listowel      1m Stks  233380666  24/09/2024 16:20:00\n",
      "76          Listowel  1m1f Listed  233380661  24/09/2024 15:45:00\n",
      "77          Listowel      7f Hcap  233380656  24/09/2024 15:10:00\n",
      "78          Listowel      7f Hcap  233380651  24/09/2024 14:35:00\n",
      "79          Listowel       7f Mdn  233380646  24/09/2024 14:00:00\n",
      "\n",
      "[80 rows x 5 columns]\n"
     ]
    }
   ],
   "source": [
    "# using Horse Racing; sportId: 7 for testing. See also Get_Sports() below. \n",
    "\n",
    "df_events = pd.DataFrame(columns=['Country', 'Venue', 'Name', 'Id', 'StartTime'])  #No rows\n",
    "response = Get_Events(7)\n",
    "print(df_events)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [],
   "source": [
    "# This is a bespoke function that may help when processing a horse race\n",
    "def Get_Runners():\n",
    "    # You could loop through each event in df_events but, for testing, I am only using the first event\n",
    "    rl = df_events.iloc[0] \n",
    "    \n",
    "    # StartTime is in .net format and needs to be converted to python format before we can use it\n",
    "    dt = datetime(rl.StartTime.Year, rl.StartTime.Month, rl.StartTime.Day, \n",
    "                  rl.StartTime.Hour, rl.StartTime.Minute, rl.StartTime.Second)\n",
    "\n",
    "    # Call openMarket to ensure that this event is active.\n",
    "    print(f'Opening market {dt:%H:%M} at {rl.Venue} ({rl.Id})')\n",
    "    response = myBA.Open_Market(int(rl.Id), 1)\n",
    "    if response == '':\n",
    "        print('Market opened successfully')\n",
    "    else:\n",
    "        raise SystemExit('There was an error on Open_Market')\n",
    "    \n",
    "    # Call getPrices to get the prices object for this market\n",
    "    prices = myBA.get_Prices()\n",
    "    i = 0\n",
    "    for priceItem in prices:\n",
    "        #print(f'{i}. Selection: {priceItem.selection}; Odds Back: {priceItem.backOdds1}; Lay: {priceItem.layOdds1}' \\\n",
    "        #    f'; lastMatched: {priceItem.lastMatched}; totalMatched: {priceItem.totalMatched}')\n",
    "        df_runners.loc[len(df_runners.index)] = [rl.Id, rl.Name, priceItem.selection, \n",
    "                                                 priceItem.nonRunner, priceItem.selectionId, i]\n",
    "        i += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Opening market 14:45 at Beverley (233379806)\n",
      "Market opened successfully\n",
      "Nala Star(70258001): \n",
      "Maddelina(73656500): \n",
      "Monetize(72422023): \n",
      "Fair Call(74168367): \n",
      "Just King High(74168368): \n",
      "Pearly Squirrel(72962946): \n",
      "Coul Harswell(73115481): \n",
      "Elouises Prince(74168365): \n",
      "Bella Fortunata(73420695): \n",
      "Andalseeyagraham(74168364): \n",
      "Genius Mistake(73074145): \n"
     ]
    }
   ],
   "source": [
    "#importlib.reload(BettingAssistant)\n",
    "#myBA = BettingAssistant.BAHandler(\"c:/Program Files (x86)/Betting Assistant/BettingAssistantCom.dll\")\n",
    "\n",
    "# getHorseForm\n",
    "# Requires that a horse racing market is open on the first tab.\n",
    "# I couldn't get Betting Assistant to return any form\n",
    "# However, form is returned by getMetaData\n",
    "\n",
    "# Get_Runners is not a Betting Assistant function but I find this bespoke function useful when processing horse races\n",
    "# To use this function the df_events must be populated as shown in the example code for getEvents above.\n",
    "df_runners = pd.DataFrame(columns=['marketId', 'marketName', 'selection', 'nonRunner', 'selectionId', 'selectionIndex'])  # No rows\n",
    "response = Get_Runners()  \n",
    "#print(df_runners)\n",
    "\n",
    "# We now have a map of horse names to their Betfair Ids. We pass these Ids to getHorseForm\n",
    "for index, runner in df_runners.iterrows():\n",
    "    print(f'{runner['selection']}({runner['selectionId']}): {myBA.get_Horse_Form(str(runner['selectionId']))}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Selection: Prince Imperial; Tot Matched: 7719.13, Last Matched: 1.9\n",
      "handicap: 0.0; reductionFactor: 28.93, farSPPrice: 1.0\n",
      "nearSPPrice: 1.48; actualSPPrice: 0.0\n",
      "odds: 1.01; backAmountAvailable: 42429.88; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 1943.28\n",
      "odds: 1.02; backAmountAvailable: 5007.05; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.03; backAmountAvailable: 1708.39; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.04; backAmountAvailable: 1.99; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.06; backAmountAvailable: 5235.92; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.1; backAmountAvailable: 100.0; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.23; backAmountAvailable: 0.83; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.36; backAmountAvailable: 842.54; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.4; backAmountAvailable: 73.47; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.5; backAmountAvailable: 100.2; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.51; backAmountAvailable: 117.65; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.53; backAmountAvailable: 2.5; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.6; backAmountAvailable: 10.12; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.62; backAmountAvailable: 1.67; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.68; backAmountAvailable: 1.47; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.7; backAmountAvailable: 237.32; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.71; backAmountAvailable: 13.0; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.72; backAmountAvailable: 13.0; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.73; backAmountAvailable: 13.0; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.74; backAmountAvailable: 13.0; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.75; backAmountAvailable: 33.0; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.76; backAmountAvailable: 13.98; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.77; backAmountAvailable: 20.48; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.78; backAmountAvailable: 20.48; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.79; backAmountAvailable: 25.07; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.8; backAmountAvailable: 7.48; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.81; backAmountAvailable: 8.34; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.82; backAmountAvailable: 15.48; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.83; backAmountAvailable: 7.48; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.84; backAmountAvailable: 7.48; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.85; backAmountAvailable: 5.58; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.86; backAmountAvailable: 51.15; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.87; backAmountAvailable: 18.56; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.88; backAmountAvailable: 9.41; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.89; backAmountAvailable: 12.18; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.9; backAmountAvailable: 56.13; layAmountAvailable: 0.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.93; backAmountAvailable: 0.0; layAmountAvailable: 20.86 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.94; backAmountAvailable: 0.0; layAmountAvailable: 58.77 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.95; backAmountAvailable: 0.0; layAmountAvailable: 7.69 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.96; backAmountAvailable: 0.0; layAmountAvailable: 5.7 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.97; backAmountAvailable: 0.0; layAmountAvailable: 124.37 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 1.98; backAmountAvailable: 0.0; layAmountAvailable: 30.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.0; backAmountAvailable: 0.0; layAmountAvailable: 22.21 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.02; backAmountAvailable: 0.0; layAmountAvailable: 5.58 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.04; backAmountAvailable: 0.0; layAmountAvailable: 5.48 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.06; backAmountAvailable: 0.0; layAmountAvailable: 5.48 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.08; backAmountAvailable: 0.0; layAmountAvailable: 5.74 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.1; backAmountAvailable: 0.0; layAmountAvailable: 161.23 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.2; backAmountAvailable: 0.0; layAmountAvailable: 97.31 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.24; backAmountAvailable: 0.0; layAmountAvailable: 5.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.34; backAmountAvailable: 0.0; layAmountAvailable: 5.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.4; backAmountAvailable: 0.0; layAmountAvailable: 3.1 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.44; backAmountAvailable: 0.0; layAmountAvailable: 5.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.48; backAmountAvailable: 0.0; layAmountAvailable: 5.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.5; backAmountAvailable: 0.0; layAmountAvailable: 211.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.52; backAmountAvailable: 0.0; layAmountAvailable: 5.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.56; backAmountAvailable: 0.0; layAmountAvailable: 5.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.6; backAmountAvailable: 0.0; layAmountAvailable: 1.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.62; backAmountAvailable: 0.0; layAmountAvailable: 17.82 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.8; backAmountAvailable: 0.0; layAmountAvailable: 4.44 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.88; backAmountAvailable: 0.0; layAmountAvailable: 10.11 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.9; backAmountAvailable: 0.0; layAmountAvailable: 5.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 2.98; backAmountAvailable: 0.0; layAmountAvailable: 1.53 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 3.0; backAmountAvailable: 0.0; layAmountAvailable: 148.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 3.05; backAmountAvailable: 0.0; layAmountAvailable: 3.9 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 3.15; backAmountAvailable: 0.0; layAmountAvailable: 7.46 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 3.3; backAmountAvailable: 0.0; layAmountAvailable: 3.48 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 3.4; backAmountAvailable: 0.0; layAmountAvailable: 3.33 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 3.65; backAmountAvailable: 0.0; layAmountAvailable: 3.02 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 3.8; backAmountAvailable: 0.0; layAmountAvailable: 2.86 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 4.4; backAmountAvailable: 0.0; layAmountAvailable: 200.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 5.7; backAmountAvailable: 0.0; layAmountAvailable: 5.53 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 7.2; backAmountAvailable: 0.0; layAmountAvailable: 1.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 8.0; backAmountAvailable: 0.0; layAmountAvailable: 14.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 17.0; backAmountAvailable: 0.0; layAmountAvailable: 19.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 18.0; backAmountAvailable: 0.0; layAmountAvailable: 8.49 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 21.0; backAmountAvailable: 0.0; layAmountAvailable: 4.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 34.0; backAmountAvailable: 0.0; layAmountAvailable: 18.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 55.0; backAmountAvailable: 0.0; layAmountAvailable: 21.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 90.0; backAmountAvailable: 0.0; layAmountAvailable: 3.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 100.0; backAmountAvailable: 0.0; layAmountAvailable: 501.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 160.0; backAmountAvailable: 0.0; layAmountAvailable: 2.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 190.0; backAmountAvailable: 0.0; layAmountAvailable: 5.71 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 200.0; backAmountAvailable: 0.0; layAmountAvailable: 0.1 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 230.0; backAmountAvailable: 0.0; layAmountAvailable: 1.1 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 400.0; backAmountAvailable: 0.0; layAmountAvailable: 0.1 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 500.0; backAmountAvailable: 0.0; layAmountAvailable: 0.01 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n",
      "odds: 900.0; backAmountAvailable: 0.0; layAmountAvailable: 1.0 totalBSPBackAmountAvailable): 0.0; totalBSPLayAmountAvailable: 0.0\n"
     ]
    }
   ],
   "source": [
    "# getMarketDepth\n",
    "response = myBA.get_Market_Depth(True)  # Set to False to test getMarketDepthComplete event\n",
    "\n",
    "# Using first element rather than looping through the entire list\n",
    "resp = response[0]\n",
    "print(f'Selection: {resp.selection}; Tot Matched: {resp.totalAmountMatched}, Last Matched: {resp.lastPriceMatched}')\n",
    "print(f'handicap: {resp.handicap}; reductionFactor: {resp.reductionFactor}, farSPPrice: {resp.farSPPrice}')\n",
    "print(f'nearSPPrice: {resp.nearSPPrice}; actualSPPrice: {resp.actualSPPrice}')\n",
    "for md in resp.prices:\n",
    "    print(f'odds: {md.odds}; backAmountAvailable: {md.backAmountAvailable}; layAmountAvailable: {md.layAmountAvailable}', \n",
    "          f'totalBSPBackAmountAvailable): {md.totalBSPBackAmountAvailable}; totalBSPLayAmountAvailable: {md.totalBSPLayAmountAvailable}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Opening market 15:33 at Pontefract (233154735)\n",
      "Market opened successfully\n",
      "selection: Likleman; saddleCloth: 10; jockey:  Aiden Brookes; trainer:  S G West\n",
      "owner:  Mr C R Hirst; ageWeight:  3/8-10; jockeyClaim:  3; bred:  \n",
      "dam:  Lynique/IRL/2014; sire:  Footstepsinthesand/GBR/2002; damSire:  Dylan Thomas/IRL/2003; colourSex:  b/G\n",
      "form:  630571; officialRating:  51; foreCastPrice:  7\n",
      "daysSinceLastRun:  15; wearing:  ; stallDraw:  6\n"
     ]
    }
   ],
   "source": [
    "# getMetaData\n",
    "\n",
    "# Get_Runners is not a Betting Assistant function but I find this bespoke function useful when processing horse races\n",
    "# To use this function the df_events must be populated as shown in the example code for getEvents above.\n",
    "# This snippet is also used in getHorseForm\n",
    "df_runners = pd.DataFrame(columns=['marketId', 'marketName', 'selection', 'nonRunner', 'selectionId', 'selectionIndex'])  # No rows\n",
    "response = Get_Runners()  \n",
    "#print(df_runners)\n",
    "name = df_runners.iloc[0]['selection']\n",
    "\n",
    "# Again, just using the first runner rather than a loop through all the elements\n",
    "resp = myBA.get_Meta_Data(name)\n",
    "#print(resp)\n",
    "print(f'selection: {name}; saddleCloth: {resp.saddleCloth}; jockey: {resp.jockey}; trainer: {resp.trainer}')\n",
    "print(f'owner: {resp.owner}; ageWeight: {resp.ageWeight}; jockeyClaim: {resp.jockeyClaim}; bred: {resp.bred}')\n",
    "print(f'dam: {resp.dam}; sire: {resp.sire}; damSire: {resp.damSire}; colourSex: {resp.colourSex}')\n",
    "print(f'form: {resp.form}; officialRating: {resp.officialRating}; foreCastPrice: {resp.forecastPrice}')\n",
    "print(f'daysSinceLastRun: {resp.daysSinceLastRun}; wearing: {resp.wearing}; stallDraw: {resp.stallDraw}')\n",
    "\n",
    "# WWarning, I found this a bit patchy as sometimes BA did not return any MetaData."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1. Selection: Likleman; Odds Back: 6.0; Lay: 12.0; lastMatched: 5.9; totalMatched: 6.0\n",
      "2. Selection: Mcted; Odds Back: 6.2; Lay: 7.4; lastMatched: 6.2; totalMatched: 71.56\n",
      "3. Selection: Chicago Gal; Odds Back: 6.6; Lay: 16.0; lastMatched: 7.0; totalMatched: 2.85\n",
      "4. Selection: Masque Of Anarchy; Odds Back: 8.2; Lay: 9.0; lastMatched: 7.8; totalMatched: 32.57\n",
      "5. Selection: Molinari; Odds Back: 8.6; Lay: 21.0; lastMatched: 8.6; totalMatched: 40.83\n",
      "6. Selection: Kalikapour; Odds Back: 8.4; Lay: 11.0; lastMatched: 8.2; totalMatched: 10.06\n",
      "7. Selection: Defence Treaty; Odds Back: 9.2; Lay: 22.0; lastMatched: 0.0; totalMatched: 0.0\n",
      "8. Selection: Love Your Work; Odds Back: 14.5; Lay: 23.0; lastMatched: 13.5; totalMatched: 2.0\n",
      "9. Selection: Edwardtheninth; Odds Back: 13.0; Lay: 36.0; lastMatched: 13.5; totalMatched: 10.76\n",
      "10. Selection: Edwina Sheeran; Odds Back: 36.0; Lay: 980.0; lastMatched: 0.0; totalMatched: 0.0\n"
     ]
    }
   ],
   "source": [
    "# getPrices (There must be an OPEN market on the first tab for this snippet to work)\n",
    "prices = myBA.get_Prices()\n",
    "i = 1\n",
    "for priceItem in prices:\n",
    "    print(f'{i}. Selection: {priceItem.selection}; Odds Back: {priceItem.backOdds1}; Lay: {priceItem.layOdds1}' \\\n",
    "          f'; lastMatched: {priceItem.lastMatched}; totalMatched: {priceItem.totalMatched}')\n",
    "    i = i + 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Likleman   10\n",
      "Mcted   7\n",
      "Chicago Gal   6\n",
      "Masque Of Anarchy   5\n",
      "Molinari   1\n",
      "Kalikapour   3\n",
      "Defence Treaty   8\n",
      "Love Your Work   2\n",
      "Edwardtheninth   9\n",
      "Edwina Sheeran   4\n"
     ]
    }
   ],
   "source": [
    "# getSaddleCloth\n",
    "\n",
    "# Please run getMetaData to populate the df_runners dataframe\n",
    "\n",
    "for index, runner in df_runners.iterrows():\n",
    "    resp = myBA.get_Saddle_Cloth(runner['selection'])\n",
    "    print(f'{runner['selection']}   {resp}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sport: Horse Racing - Today's Card; sportId: 1000000\n",
      "sport: Greyhound - Today's Card; sportId: 2000000\n",
      "sport: Tennis; sportId: 2\n",
      "sport: Soccer; sportId: 1\n",
      "sport: Ice Hockey; sportId: 7524\n",
      "sport: Basketball; sportId: 7522\n",
      "sport: Golf; sportId: 3\n",
      "sport: Greyhound Racing; sportId: 4339\n",
      "sport: Politics; sportId: 2378961\n",
      "sport: Australian Rules; sportId: 61420\n",
      "sport: Baseball; sportId: 7511\n",
      "sport: Horse Racing; sportId: 7\n",
      "sport: Rugby Union; sportId: 5\n",
      "sport: Rugby League; sportId: 1477\n",
      "sport: Cricket; sportId: 4\n",
      "sport: Boxing; sportId: 6\n",
      "sport: Esports; sportId: 27454571\n",
      "sport: American Football; sportId: 6423\n",
      "sport: Gaelic Games; sportId: 2152880\n",
      "sport: Motor Sport; sportId: 8\n",
      "sport: Special Bets; sportId: 10\n",
      "sport: Handball; sportId: 468328\n",
      "sport: Darts; sportId: 3503\n",
      "sport: Volleyball; sportId: 998917\n",
      "sport: Cycling; sportId: 11\n",
      "sport: Mixed Martial Arts; sportId: 26420387\n",
      "sport: Snooker; sportId: 6422\n",
      "sport: Soccer - Fixtures; sportId: 3000000\n"
     ]
    }
   ],
   "source": [
    "# getSports\n",
    "sports = myBA.Get_Sports()\n",
    "\n",
    "for sport in sports:\n",
    "    print(f'sport: {sport.sport}; sportId: {sport.sportId}')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Odds: 5.9; totalBspBackMatchedAmount: 0.0;         totalBspLiabilityMatchedAmount: 0.0; totalMatchedAmount: 0.48\n",
      "Odds: 6.0; totalBspBackMatchedAmount: 0.0;         totalBspLiabilityMatchedAmount: 0.0; totalMatchedAmount: 5.0\n",
      "Odds: 6.4; totalBspBackMatchedAmount: 0.0;         totalBspLiabilityMatchedAmount: 0.0; totalMatchedAmount: 0.52\n"
     ]
    }
   ],
   "source": [
    "# getTradedVolume\n",
    "\n",
    "# Using the selection name from getMetaData function (above)\n",
    "response = myBA.Get_Traded_Volume('Likleman')\n",
    "\n",
    "for tv in response:\n",
    "    print(f'Odds: {tv.odds}; totalBspBackMatchedAmount: {tv.totalBspBackMatchedAmount}; \\\n",
    "        totalBspLiabilityMatchedAmount: {tv.totalBspLiabilityMatchedAmount}; totalMatchedAmount: {tv. totalMatchedAmount}')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Current logged on User name is HiArt99Trade\n"
     ]
    }
   ],
   "source": [
    "importlib.reload(BettingAssistant)\n",
    "myBA = BettingAssistant.BAHandler(\"c:/Program Files (x86)/Betting Assistant/BettingAssistantCom.dll\")\n",
    "\n",
    "# getUserName\n",
    "print(f'Current logged on User name is {myBA.Get_User_Name()}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1. Bet reference is 361558434027\n",
      "2. Bet reference is 361558434028\n",
      "3. Bet reference is 361558434029\n",
      "4. Bet reference is 361558434030\n",
      "5. Bet reference is 361558434031\n",
      "6. Bet reference is 361558434032\n",
      "7. Bet reference is 361558434033\n",
      "8. Bet reference is 361558434034\n",
      "9. Bet reference is 361558434035\n",
      "10. Bet reference is 361558434036\n",
      "All unmatched bets cancelled.\n"
     ]
    }
   ],
   "source": [
    "# layField\n",
    "i = 1\n",
    "response = myBA.Lay_Field(1.01, 2.10)\n",
    "for resp in response:\n",
    "    print(f'{i}. Bet reference is {resp}')\n",
    "    i += 1\n",
    "\n",
    "time.sleep(5)\n",
    "\n",
    "# cancelAllBets\n",
    "response = myBA.cancel_All_Bets()\n",
    "if response == '':\n",
    "    print('All unmatched bets cancelled.')\n",
    "else:\n",
    "    print(f'Error message from cancel_All_Bets: {response}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "importlib.reload(BettingAssistant)\n",
    "myBA = BettingAssistant.BAHandler(\"c:/Program Files (x86)/Betting Assistant/BettingAssistantCom.dll\")\n",
    "\n",
    "# loadQuickPickList\n",
    "response = myBA.Load_QuickPick_List(1, True)\n",
    "if not response == '':\n",
    "    raise SystemExit('There was an error on loading the quickpick list')\n",
    "\n",
    "response = myBA.Load_QuickPick_List(3, False)\n",
    "if not response == '':\n",
    "    raise SystemExit('There was an error on loading the quickpick list')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Response from openFirstQuickPickMarket is OK\n"
     ]
    }
   ],
   "source": [
    "# openFirstQuickPickMarket\n",
    "response = myBA.Open_First_QuickPick_Market()\n",
    "print(f'Response from openFirstQuickPickMarket is {response}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Response from openLastQuickPickMarket is OK\n"
     ]
    }
   ],
   "source": [
    "# openLastQuickPickMarket\n",
    "response = myBA.Open_Last_QuickPick_Market()\n",
    "print(f'Response from openLastQuickPickMarket is {response}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Market opened successfully\n"
     ]
    }
   ],
   "source": [
    "# openMarket\n",
    "# You may need to run getEvents (above) to get a valid Id\n",
    "response = myBA.Open_Market(233154735, 1)\n",
    "if response == '':\n",
    "    print('Market opened successfully')\n",
    "else:\n",
    "    print('There was an error on Open_Market')\n",
    "    \n",
    "# For more examples of Open_Market there are several functions that use Open_Market in their test code, Get_Runners for example."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Response from openNextQuickPickMarket is OK\n"
     ]
    }
   ],
   "source": [
    "# openNextQuickPickMarket\n",
    "response = myBA.Open_Next_QuickPick_Market()\n",
    "print(f'Response from openNextQuickPickMarket is {response}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Response from openPreviousQuickPickMarket is OK\n"
     ]
    }
   ],
   "source": [
    "# openPreviousQuickPickMarket\n",
    "response = myBA.Open_Previous_QuickPick_Market()\n",
    "print(f'Response from openPreviousQuickPickMarket is {response}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Bet placed. Reference: 361566646808\n"
     ]
    }
   ],
   "source": [
    "# placeBet\n",
    "bet_Ref = myBA.place_Bet(1, 'B', 1000, 0.10, True, 'Anything you want!', -1, keepBetType=0)\n",
    "print(f'Bet placed. Reference: {bet_Ref}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1. Bet placed. Reference: 362195437832\n",
      "2. Bet placed. Reference: None\n",
      "3. Bet placed. Reference: None\n",
      "4. Bet placed. Reference: None\n"
     ]
    }
   ],
   "source": [
    "# placeBets\n",
    "# Note that many of the parameters are passed as lists, this is important!\n",
    "bet_Ref = myBA.Place_Bets([0, 1, 2], ['B', 'L', 'B'], [1000, 1.01, 1000], \n",
    "                          [0.10, 2.00, 0.20], True, ['Anything', 'you', 'want!'], 10, 2)\n",
    "\n",
    "i = 1\n",
    "for bet in bet_Ref:\n",
    "    print(f'{i}. Bet placed. Reference: {bet}')\n",
    "    i += 1\n",
    "\n",
    "# WARNING !!!\n",
    "# For whatever reason only the reference for the last bet made is returned.\n",
    "# WARNING !!!\n",
    "# 'do not cancel when market turns in play' (KeepBet = 1) or 'Convert to SP when market turns in play' (KeepBet = 2)\n",
    "# seem to have no effect.\n",
    "# Maybe my python powers are not that strong.\n",
    "\n",
    "# Remember to cancel any bets placed by this call"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Response from refreshMarkets: True\n"
     ]
    }
   ],
   "source": [
    "# refreshMarkets\n",
    "\n",
    "print(f'Response from refreshMarkets: {myBA.Refresh_Markets()}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# setIPAddress\n",
    "\n",
    "# I have not included setIPAddress in the python file as it is dangerous to muck about with and testing \n",
    "# requires that I muck around with it!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Response from setQuickPickAutoSelect: \n"
     ]
    }
   ],
   "source": [
    "# setQuickPickAutoSelect\n",
    "# This setting if found on the Market tab > Auto Select Markets. You will need to manually cancel these changes\n",
    "print(f'Response from setQuickPickAutoSelect: {myBA.Set_QuickPick_Auto_Select(True, 0)}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Bet placed. Reference: 361649592728\n",
      "Reference: 361649592728; price: 1000.0; requestedSize: 2.5; betStatus: U;\n",
      "The response from updateBet (odds) is: newRef 361649593926; stakeCancelled 2.5; resultCode OK\n",
      "Reference: 361649593926; price: 900.0; requestedSize: 2.5; betStatus: U;\n",
      "The response from updateBet (stake) is: newRef 361649593926; stakeCancelled 0.5; resultCode BET_CANCELLED_REMAINING_UNMATCHED\n",
      "Reference: 361649593926; price: 900.0; requestedSize: 2.0; betStatus: U;\n",
      "cancel_Bet with event Id  cancelled 2.0 of unmatched staked for bet reference 361649593926\n"
     ]
    }
   ],
   "source": [
    "# updateBet\n",
    "# Step 1 - create a bet to be updated\n",
    "bet_Ref = myBA.place_Bet(1, 'B', 1000, 2.50, True, 'Anything you want!', -1, keepBetType=0)\n",
    "print(f'Bet placed. Reference: {bet_Ref}')\n",
    "\n",
    "# Step 2 - confirm odds and stake of this bet\n",
    "time.sleep(1)\n",
    "\n",
    "resp1 = myBA.get_Bet(bet_Ref, 1)\n",
    "print(f'Reference: {resp1.ref}; price: {resp1.price}; requestedSize: {resp1.requestedSize}; betStatus: {resp1.betStatus};') \n",
    "\n",
    "# Step 3 - Amending the odds\n",
    "resp2 = myBA.Update_Bet(bet_Ref, resp1.price, resp1.requestedSize, 900, resp1.requestedSize)\n",
    "print(f'The response from updateBet (odds) is: newRef {resp2.newRef}; stakeCancelled {resp2.stakeCancelled}; resultCode {resp2.resultCode}')\n",
    "\n",
    "# Step 4 - confirm odds have changed\n",
    "time.sleep(1)\n",
    "\n",
    "resp3 = myBA.get_Bet(resp2.newRef, 1)\n",
    "print(f'Reference: {resp3.ref}; price: {resp3.price}; requestedSize: {resp3.requestedSize}; betStatus: {resp3.betStatus};') \n",
    "\n",
    "# Step 5 - Amending the stake\n",
    "# NB you can only adjust stake downwards. To increase stake you make a new bet.\n",
    "resp4 = myBA.Update_Bet(resp3.ref, resp3.price, resp3.remainingSize, resp3.price, 2.00)\n",
    "time.sleep(1)\n",
    "if resp4.newRef == 0 or resp4.newRef == '0':\n",
    "    newRef = resp3.ref\n",
    "else:\n",
    "    newRef = resp4.newRef\n",
    "    \n",
    "print(f'The response from updateBet (stake) is: newRef {newRef}; stakeCancelled {resp4.stakeCancelled}; resultCode {resp4.resultCode}')\n",
    "\n",
    "# Step 5 - confirm stakes have changed\n",
    "resp5 = myBA.get_Bet(newRef, 1)\n",
    "print(f'Reference: {resp5.ref}; price: {resp5.price}; requestedSize: {resp5.requestedSize}; betStatus: {resp5.betStatus};') \n",
    "\n",
    "# Step 6 - Cancel the bet\n",
    "response = myBA.cancel_Bet(newRef, resp5.marketId)\n",
    "print(f'cancel_Bet with event Id  cancelled {response} of unmatched staked for bet reference {newRef}')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
