Sectionals an Idiots Guide Part 1

If you have been hibernating for the last five years or perhaps you are easily distracted by the gradual overturning of Brexit or the idea that animal cruelty is the reason for Horse Racing’s decline with the betting public, then you may have overlooked the increasing prevalence of electronic sectional times. At the Races have been publishing sectionals for quite a while now on their web site and they form an integral part of their daily form reporting. It is refreshing to see a racing publication actually attempt to innovate in its provision in a manner that benefits punters, unlike other publications that appear to do exactly the opposite.

Perhaps the main informational gain from sectional times is that they can tell us how a race has been run. We have long had final times for races, for example a 5f race at Epsom may clock 60 seconds but what we have not been aware of is how fast or slow was the first furlong, the second furlong and so on. This is what we mean when we talk about sectionals.

When I was in my twenties and out running 10k road races I recall one particular summer when I was in rude health and fitness. In training I could run 8 miles at 6 minute mile pace. One particular summer Sunday I arrived at a 10k race just outside York and decided to see what it would be like to attempt to run with the elite runners from the start. I wanted to experience that opening pace and see how long I could go with it. If you had asked me before the race what I thought would happen I would have guessed staying with them for maybe half a mile at best. What actually happened shocked me, not only could I not lie up with the leaders at all, well maybe 50 yards, but the effort of trying decimated my whole race. I never attempted it again.

So how can we attempt to measure whether a horse has run an even sort of race which like me maximizes its chance of running its best overall time or perhaps the way it has run has disadvantaged it and of course that disadvantage does not have to come from a kamikaze opening section. It could be suicidal burst somewhere in the race akin to Said Ouita’s outrageous run for home from 500 metres out in the 1983 world athletic championships, handing the gold to Steve Cram.

One approach would be to calculate average times for various sections of races by race distance. In other words what is the average time (sometimes called par time) for the first 2f of say all 5f races. The problem with this is our courses are so different in conformation that the waters would be muddied by a course having a downhill opening section like Epsom compared to a flat or uphill section on another track. We need therefor to calculate average times for sections for each track. There are still problems however, what about the going. A race may appear to have a slow sectional but in fact we are comparing the race run on soft going with the par sectional that on average has been calculated from good going.

In attempt to get around this Timeform have come up with what we could call an in race method of evaluating pace so that we can evaluate whether a horse within a race or the race overall has been run fast, even or slow in terms of its early pace. Let us take a simple example with nice round numbers.

Slowcoach runs in a selling plater over 5f at Epsom, he is particularly slow and finishes the race in 100 seconds covering the final 2f in 30 seconds. We can calculate the relationship of his final 2f to his overall time with a little Math.

His overall time we will call OT
His final section time we will call fst
The distance of the final sectional we will call sd
The overall race distance we will call D.

The relationship between the sectional time and his overall time can be expressed as

(OT/fst) X (sd/D) X 100

or in Slowcoach’s case

(100/30) X (2/5) X 100 = 133.33 (race finish percentage for Slowcoach)

Now this is an extreme example after all Slowcoach is pretty darn slow. It’s also a number that may say something about how he ran his race (more on that later although a number like 133.3 might suggest he stopped for a nibble of grass after 2f) but what about how the race was run overall. I mean I ran that 10k race at an inefficient rate for me but maybe the winner ran an even race for him. We can carry out the same calculation for the winner of Slowcoaches race and hence get a number for his/her performance in terms of final sectional vs overall time. This may help us to get a picture of how the race was generally run or at least in terms of the winner.

Let us imagine the winner comes out with a race finish percentage figure of 101.5, the problem is we still do not know what that means. Let’s face it the final uphill 2f at Beverly is likely to produce bigger fst numbers in that equation than the final downhill 2f at Epsom. If you play around with that fst number above you will see that if you increase it the final number gets smaller. So a smaller final number means the horse must have gone faster early in the race hence the increase in the final section or fst time (or perhaps the last 2f is akin to Mount Everest). That is the first thing to take out, bigger race percentage numbers eg 133.33 mean slower early pace. We still do not know if 101.5 however represents fast even or slow early pace unless we have some benchmark to compare to. What we need is an average or median for races run at that track over 5f, in order to get around the Mount Everest problem. If the median comes out at 100 then we know that the 101.5 winner has run slightly slower early on than is perhaps ideal. If his final number is below 100 then he has run faster than ideal early on.

Of course different tracks and distances will have different medians for these race finish percentage numbers, they will not all be 100 but they all give a benchmark with which to compare a horses run with on that particular track.

Try calculating the race finish percentage figure for the following horse using the last 2f as the final sectional fst for this Lingfield race over 8 furlongs.

DIVINE MESSENGER 2f-1f 11.0s 1f-Finish 11.6s Finish/final time of race 97.2s

Now check out your result at by clicking on the sectional tools tab at

https://www.attheraces.com/racecard/Lingfield/08-March-2019/1410

One final point, ATR has a race final percentage figures displayed next to the hotbar. For Divine Messengers race its 107.0. This is not the same as Divine Messengers race percentage figure which is 108.0. This is because the race percentage figure of 107.0 is calculated as follows

Take the race leader time at 2f out, Majestic Moon 74.5
Subtract it from the race winners final time of 97.2 giving 22.7
Use this as the final sectional time in the equation

This is a tricky subject so please feel free to correct any misunderstandings in the above. Please indicate how helpful this was below

Advertisements

Regressing Final Call Sectionals

Today’s Southwell card has been decimated by the Arena trainers and owners ban over decreased prize money. The result is very small fields and further evidence of the farcical state of UK racing. Meanwhile the BHA are working on more important matters like whether 9yo’s can be made to win more races and benefit the bookmakers who will welcome the increased randomness. Ironic when one considers that they are the root cause of this prize money problem in the UK.

Small fields however do allow a speedy experiment in sectional regression to analyse the chances of todays runners in the 5.10 6f race. Taking the final 2f times and the 6f to 2f times of all class 6 races over 6f on standard going at Southwell allows one to play around with regression on the latter to predict the former. In other words if a horse runs the first 4f in x seconds what would you expect it to run the final 2f if given all previous placed performances run under these conditions. Using this formula we can look at the four runners last runs over Southwell 6f which all happen to be class 6 on standard going. The 3yo runner does not have a run and so will be hard to assess here and Pearl Noirs run go’s back some two years having been campaigned almost exclusively over 5f. Never the less lets take a look at what the numbers say.

Jazz Legend ran last time out 49.9 and 26.9 but his predicted final call was 26.2

Televoi ran 51.5 and 25.7 off a predicted 25.6

Jazz ran in the same race as above with 50.6 and 26.4 off a predicted 25.9

So far Televoi looks the better shot with a much closer to predicted final call

Pearl Noir ran 2 years ago 50.4 and 26.2 off a predicted 26.0

Pearl Noir would perhaps be the bigger danger to Televoi with the 3yo being hard to assess having never run at Southwell

Current odds

Televoi 2.32
Jazz Legend 2.42
Thedevilinneville 8.6
Pearl Noir 19.0

Level Stakes and Percentage Bank Betting

So you have developed a winning system, a profitable model or maybe you can just read form and grind out impressive returns. The work is done, you can start betting and watch the profit roll in, except things don’t quite work out as you would like. Should you have bet levels stakes instead of perhaps being greedy and operating a percentage of bank stake in the hope that the latter would accelerate growth and put when to increase stakes on auto pilot.
Maybe you should just give it a bit longer after all the results show levels stakes are doing OK and maybe your percentage bank betting is just taking a bit longer to crank up.

Joseph Buchdahl does an excellent job of examining the pro’s and con’s of levels takes v proportional bank staking in the following article.

https://www.pinnacle.com/en/betting-articles/Betting-Strategy/level-vs-percentage-staking/PTG2LLKF9SH3TMUY

Well not much to add one might think, but it occurred to me that there are other considerations to well, take into consideration. How does the real world of getting on impact various forms of staking. My main thoughts on this revolve around knowing your betting pattern, especially in terms of odds. It is easy to think that proportional betting is the way to go on paper but in reality that theoretical £500 stake at 80/1 is not going to happen even betting just before the off on Betfair. Even levels stakes will run into getting on problems when you decide perhaps at the end of a year to increase stakes.

This is where another form of staking should be considered namely variable stakes. Variable stakes involve putting a proportional amount on to win a fixed return. If you are backing a 10/1 shot and your fixed return is £1000, you would invest £100. If it happened to be even money you would invest £1000. The advantage of this staking is that you are putting more on the odds which will allow you to put more on. Another argument is that if your method is not making reasonable returns to variable stakes it is much more likely to be a mirage in terms of long term profitability.

Variable staking does not quite give you the same roller coaster ride as levels stakes although it clearly can inflict pain when an even money shot loses and a 20/1 shot go’s in but the long term profit of variable staking is perhaps more realistic due to the allowed stakes imposed by the odds you are taking.
The bottom line is know your betting method/past results, take a look at variable staking and see how it stacks up and remember always bet with the exchanges because that is where you will end up anyway.

Bookmaker Trainer Connections

Is it ethical for race horse trainers and indeed jockeys to have financial connections with bookmakers. Most punters would think it is unethical and I would tend to agree. Even if you cannot stop under the radar connections, the sport still has to be seen to be clean and financial ties between trainers and bookmakers is just another example of the degree to which bookmakers run racing.

There has been plenty of talk on this subject recently on Twitter and forums so I decided to take a look at 10.00am prices and track the occurance of top priced bookmaker by trainer. The bookmaker had to be outright top priced and not joint and the data spans from September 2018 through to today, the 20th February 2019.

The most frequent top priced bookmaker is Matchbook and their most frequent trainer connection when top priced was Richard Fahey who they got right most of the time. They had one of his horses top priced 84 times and the total profit/loss to Betfair SP on these horse amounted to -34.04 from an average odds of 13.07/1 (14.07 to decimal odds).

Matchbook do not however have a flawless crystal ball. in next was D Skelton who they tended to get wrong with 80 top priced horses returning +77.44 before com’ off average odds of 10.16/1.

So what about the most high profile trainer bookmaker connection, Nicky Henderson and Unibet. Unibet have been outright top priced 8 times with Nicky Henderson for a BFSP loss of -0.21, hardly suspicious but with all these numbers probably worth a revisit in 12 months time.

For the time being be cautious when R A Fahey is outright top priced with any bookmaker at 10am until bigger samples say otherwise.

Comparing Betfair and Betdaq SP

Tags

At the age of 14 the quote ‘I know what I like and I like what I know’ did not really resonate with me quite as the Music teacher hoped even though I understood what he was getting at as he tried to give us a reason why we should open our minds to the possibility of enjoying Beethoven. I have since thought that he missed a trick and should have made his appeal through the soundtrack to A Clockwork Orange which was sweeping through my 4th form at
that particular time. I think then he would have had our attention, particularly if he had turned up in white’s, a bowler, boots and single false eyelash.

We are all still guilty at various times of liking what we know and for some that means not being able to embrace the better winning prospects that exist on Betfair but for Betfarians it may be simply not checking out the other exchanges
that are perhaps making in roads into Betfair’s dominance.

One particular area I have been meaning to look at is the variance between Betfair SP and Betdaq’s XSP. This could be quite useful if you are a users of Betfair SP and are concerned about canibalising your price. If Betdaq offer comparable prices then splitting between the two may be an option in order to spread the erosion.

I decided to take a look at relative returns for the first week of January 2019 for UK racing. My data produced 1583 individual horse returns.

First looking at the average price across all horses showed the following

Average all prices Betfair SP 65.0
Average all prices Betdaq SP 66.91

Clear win for Betdaq over Betfair here, but its winners that really count.

Average price where finpos = 1 Betfair 7.76
Average prices where finpos = 1 Betdaq 7.94

Betdaq again comes out ahead and furthermore the average winning prices were better for Betdaq on individual days

In order to enlarge the place sample I looked at all horse that finished in the first 3

Average price where finpos less than 4 Betfair 12.18
Average price where finpos less than 4 Betdaq 12.87

Finally the number of occurances when each return beat the other

Count Betfair greater than Betdaq 732
Count Betdaq greater than Betfair 824

Across all bands Betdaq was superior to Betfair SP during the first week of January. This I have to admit surprised me a little, especially the cross blanket domination. Betting at exchange SP is often used as a fall back against missing a price and perhaps both exchanges should be considered.

Beethoven anyone ?, prefer Rachmaninov myself.

Switching To The Exchanges

Around 2013 I finally got fed up with betting with bookmakers, in fact it started way before then it was just that around this time I decided to seriously look at Exchange betting only. I suffered from all the anxiety you are probably feeling if you are used to making a few quid betting with bookmakers. The lack of liquidity in the morning on the exchanges will mean I wont be able to do what I am used to doing which is decide what I am betting on, check who has best odds and then proceed to bet with that bookmaker/s, occasionally even on the exchange to smaller amounts. It seemed that deciding what to bet on and then choosing the book with the highest price was a criminal offence in the eye of bookmakers and to legitimize their actions they would lump all such clients under the banner of arbers or filthy arbers as they like to call them. An activity which bookmakers of course never take part in.

So grumbles aside what is the best way to make this transition. These ideas are based solely on my experience and hopefully others will add comments. The first thing you could do is track what lies ahead with your current approach. Any smart punter who is winning with bookmakers should be preparing for the inevitable by additionally placing small breadcrumb bets at Betfair SP. Maybe £2 on all your current bets. This will allow you to gauge where you are in relation to your current activity and the exchanges. You may not even have to log these bets if you currently log all your bookmaker bets (you should be) as you can look up Betfair SP and insert the prices into your spreadsheet and see how you would have faired.

The reason for doing this is it will enable you to see whether your current methods need binning or perhaps just adding to in order to boost or hopefully boost profit.

So lets assume you have done the above over a period of time and you are making between 5% and 10% with Bookmakers but losing 1% with Betfair after commission. This is just an example, I am sure everyone will have different profiles and it is difficult to be specific. My personal conversion showed that my betting was profitable to BFSP but only to around +1% and given that I was having around 3,500 bets per year this meant a paltry 35 pts per year instead of my average 350 pts. It was clear that the market got smarter as time moved through the morning towards the off.

I realized that in order to make meaningful amounts I would have to shift my game up to a very high turnover activity with low ROI but decent returns and this would mean automation. I also realized that small return approaches which normally with bookmakers you would normally cast in the not worth the effort bin suddenly have a different value. If you can automate and some approach makes 0.5% per year then run it as it contributes to lowering your commission and helps keep you away from the despicable premium charge.

OK automation may not be within your skill set but their are off the shelf programs that can help with your automated betting. Maybe even consider getting together with one or two punters with a common need and hiring a programmer. It may not be difficult to find two or three people who all have the same basic need in terms of bet execution but are plugging their own files of daily bets into the software.

I am probably going to add more to this blog entry later but for the time being I will end on these notes. Talk to other exchange players, they are usually prepared to talk about general strategies if not specific bet choice methods. Also be prepared for increased variance. When you are down at the + 2%, +3% or + 5% ROI you are going experience greater shifts around the plus and minus marks. Are decent returns possible of smaller bet samples, yes I think so. I am currently running a Machine Learning model that in testing achieve around 9.5% ROI to BFSP and on live bets is currently running at just under this from 2,400 live bets after 7 months. This bet execution is automated along with a load of other stuff but the ML bets numerically are at the threshold of executing manually. Also let us not forget that the exchanges opens up a whole new side of betting that you previously had not dabbled too much in, LAYING. If you are good at finding value based winners then you should be good at finding value based losers.

One thing is for sure, if you are any good at betting you will be forced eventually to either pack up or consider the exchanges, it is better to consider them now along side your betting so that you are prepared for a successful switch over.

Please leave a comment if you have personal experiences to add with regard to Exchange switching.

Web Scraping Race Data Part 4

Tags

In this final session we will wrap up by saving all the data to a .csv file.
I am going to save the pace figures for each horse but not the race averages, we can calculate those if we need to.

In order to omit the race average pace figure line I need to make one small amendment to the following line.

for atr in trs:

becomes

for atr in trs[:-1]:

This has simply said access all the trs one by one from the first one but slip the last one.

Each line we ouput to our file will look like the following lines

Ascot 12:40 1m 7f 152y,Beat The Judge (IRE), ,0,0
etc etc
etc etc
Wolverhampton 20:15 5f 21y,Teepee Time,11,2.6,3

I am going to call the output file pacefile.csv.I will therefore need to open this file for writing with the following statement early on in the program code

pacefile = open(‘pacefile.csv’,”w”)

Now here is the final modified final section of code.

for atr in trs[:-1]:
  outLine = raceId
  tds = atr.findAll(‘td’)
  for atd in tds:
    data = atd.text
    if (re.search(“\([0-9]”, data)):
      data = re.sub(“\(“,””,data)
      data = re.sub(“\)”,””,data)
      data = re.sub(” “,”,”,data)
    data = re.sub(‘\n’, “” , data)
    outLine = outLine + ‘,’ + data

  print (outLine)
  pacefile.write(outLine)

pacefile.close()

Notice how when we loop around each table row we assign the RaceId to a new OutLine on line 2 of the above code.
In the inner loop where we access each data column we add the data to outLine seperated by a comma.
pacefile.write outputs the line to the .csv file.

Often html tags such as tables have names which can make life easier when trying to access them.
Another important method is accessing the url contents of links. Here we do not want to access the text but we do want the url perhaps to navigate to another page. For example if the links were in a number of table columns
we could have code such as

for td in tds:
  link = td.find(‘a’, href=True)
  if (link != None):
    strlink = str(link.get(‘href’))

The only way to get used to web scraping is to practice, but it’s not for the impatient. It can be like drawing teeth at times but well worth it when the data lands.

The full program code can be copied/saved at

http://www.smartersig.com/scrapeexample.py

Let me know if this series has been helpful or not in the comments section

Web Scraping Race Data Part 3

Tags

In this session we are going to drill down into the web page and extract the data so that we can store it into a .csv file

If you recheck the pretty file we produced in the previous session you can just about see that the data is stored in tables depicted by the table tags
and the nested inner tables contain the data in rows controlled by tr tags and columns controlled by td tags.

If you add the following two lines of code to your program and run the code you will see that findAll has located all the table components and stored them in an array called tables.

tables = soup.findAll(‘table’)

print (tables[0])

Printing out tables[0] only accessed the first table in the html file. Try changing this to tables[1] and you will see that it prints out the next table level and all its inner tables. Try changing the value to 2,3 and 4

From 4 onwards you are now accessing individual data tables but we do not know how many there are or could be in future. No worries we can get round this by using the tree like hierarchy that soup contains.

Remove the print statement and replace with

tables = soup.findAll(‘table’)
outerTable = tables[2].find(‘table’)
dataTables = outerTable.findAll(‘table’)
for aTable in dataTables:
  print (aTable)
  print (“————————–“)

The above code grabs the required nested level of table and then finds all the tables within it which contain the individual data tables we need. The print out shows each table separated by the dotted line. We still need to remove the data from the HTML however in each data table. You can see from the print out that we still have lots of unwanted HTML code mixed in.

Let’s see how we can access our first piece of pure data, the race heading. Change the last two lines of code so the code now reads

for aTable in dataTables:
  caption = aTable.find(‘caption’)
  raceId = caption.text
  print (raceId)

Run the code and you should see the race headings printed off.

OK we are no ready to access the individual rows (tr’s) within each race table and each column (td’s) within the row. This will give us access to the horse name, the draw, the two pace figures. Here is the code we need to add to achieve this.

for aTable in dataTables:
  caption = aTable.find(‘caption’)
  raceId = caption.text
  print (raceId)

## this is the new code ##

 trs = aTable.findAll(‘tr’)
 for atr in trs:
    tds = atr.findAll(‘td’)
    for atd in tds:
       data = atd.text
       print (data)

Running this we can see it works except for one problem. The final pace figure on each line has brackets round it which we would like to remove.
Also there appears to be a carriage return as the second bracket is on a new line. We will nee a bit of code to clean this up but the problem is that
we only want clean up the last column, We do not for example want to remove brackets from the horse name. Here is the code for this.

for aTable in dataTables:
  caption = aTable.find(‘caption’)
  raceId = caption.text
  print (raceId)

  trs = aTable.findAll(‘tr’)
  for atr in trs:
    tds = atr.findAll(‘td’)
    for atd in tds:
      data = atd.text

## this is the new code ##

    if (re.search(“\([0-9]”, data)):
     data = re.sub(“\(“,””,data)
     data = re.sub(“\)”,””,data)
     data = re.sub(‘\n’, “” , data)
    print (data)

The above needs a little explaining. The IF statement searches the data for any opening bracket followed by a digit. This means we will only
catch the pace figures and not the brackets associated with horse nationality. If it detects this data it executes the two statements in the
body of the IF. These two statements substitute an open bracket for null and similar for a closed bracket. The backslash before the brackets is
to tell Python to interpret the brackets as a character to be substituted and not to treat it as a bracket used as part of an expression eg (a+b)* (c+d)

The final substitution is replacing all \n that’s carriage returns with null as well

Ok we seem to be getting at the required data. In the final session we will see how to tie it up so that we output this data to a file and not simply
to the screen.

Web Scraping Race Data Part 2

Tags

In this session we are going to get straight in and do some web scraping. I have set up a simple web page to scrape, you can take a look at

http://www.smartersig.com/pacedataEG.htm

When you just loaded the above data into your browser it was your browser that tidied up the presentation. The data itself is inconveniently
nestled within all the HTML tags and code that tell the browser how to create the presentation of the data.

Take a look at the underlying code by right clicking on the web page and selecting ‘view source’

What we see is mainly HTML tags and code and nestled among the gobbledygook you can just about see some of the data that actually appears in the browser when we view it.

What we need to do is tease out all the data from within this spaghetti of code and the Python library BeautifulSoup is going to help us.

Fire up a new file in Notepad and enter the following code. these are the libraries we are going to need in our new program

# import libraries

from lxml import html
import re
import requests
from bs4 import BeautifulSoup

Now we are ready to pull in the web page you have just looked at so that we can then write some code to tease out the data.
Enter the following lines in your new file under the import statements, save the file with a name of your choice eg program2.py and then run it with the
python program2.py command at the DOS prompt

url = “http://www.smartersig.com/pacedataEG.htm”
page = requests.get(url)
html_page = page.content

The variable called html_page now contains the whole of the web page content we requested, including the HTML stuff we dont want.

If we add the following line and run the program it spews out the entire HTML content to the screen

print (html_page)

We can now call on BeautifulSoup to render the page into a structure that will allow us to traverse it more easily
The following statement will do this.

soup = BeautifulSoup(html_page, “lxml”)

We can now take a look at how Beautiful soup see’s and represents the code by adding the following line and running the program

print (soup.prettify())

It would help to have this to refer to so we could save it to a text file so that we can check it more leisurely and see how the underlying
code is organised. We need to have some understanding of how the code is structured so we can tease out the data.

To save the prettify code simply add the following two statements and rerun the program to save it to a file called prettysoup.txt

soupfile = open(‘prettysoup.txt’,”w”)

soupfile.write (soup.prettify())

Now you can open the file prettysoup.txt and take a look at its structure.

In the next session we will look at how to pull out the data so that have the horse names and pace figures stored in a .csv file

Total program so far

# import libraries

from lxml import html
import re
import requests
from bs4 import BeautifulSoup

## get the page ##

url = “http://www.smartersig.com/pacedataEG.htm”
page = requests.get(url)
html_page = page.content

soup = BeautifulSoup(html_page, “lxml”)

soupfile = open(‘prettysoup.txt’,”w”)

soupfile.write (soup.prettify())

Web Scraping Race Data 1

Tags

This is the first in a series on web scraping using Python. I am going to assume that you have some basic programming skills,for example you know what a FOR loop is or an IF statement. If these terms do not mean anything to you then you probably need an introduction to basic programming in Python. I am also assuming that you are on a Windows based machine.

Web scraping is the process of gathering data from web pages and placing it into a convenient data form such as a .csv file
As an example we might want a .csv file (comma delimited flat file) of the days runners

2019-01-18,Chepstow 13:05,NH,Handicap Chase,5YO+,4,4.6,,433,Barbrook Star (IRE),etc,etc
etc
etc

Before we get stuck into the nitty gritty of scraping you are first going to need to download and install Python assuming you do not already have it. Don’t worry this is quite painless. I suggest installing Anaconda as your Python programming language source. If you do not already have Anaconda Python
then visit the following link and click on the 64 or 32 bit installer link depending on your machine. The installer will be downloaded
and you should then double click it to begin the installation process. The default settings that are offered to you should all be fine for
our purposes and the process should only take about 5 minutes.

https://www.anaconda.com/download/

Once everything has been installed check all is OK and the version of Python you have by firing up an MSDOS command window
(type cmd at the windows search engine) and then in this window type in

python –version

That’s a double dash by the way in the above

First Program

Let us finish this short first session off with our first program, the usual Hello World.
For now we will stick with rudimentary tools just to keep things simple. We will use Notepad or you can use Wordpad if you prefer.
Fire up Notepad (enter Notepad in windows search) and enter the following few lines of code

message = “Hello World”
if (“World” in message):
print (message)

Save the file with the name HelloWorld.py

Now at the DOS window prompt where you checked the python version type in

python helloworld.py

You should get the Hello World message appearing on the screen.

Try changing the
if (“World” in message):
line to
if (“world” in message):
and save and run again

Notice when you run the program now it prints nothing out because lower case world is not contained in the message.

Notice also the indentation, Python will not allow the following statement, unlike other programming languages.

if (“World” in message):
print (message)

I am not going to deliver a full blown intro to Python during this series but I may mention things that are peculiar to Python just in case you have programmed in other languages but not Python.

OK that will do for now, in the next session we will start doing some actual web scraping