9

I am trying to fetch current spot price via boto in python using get_spot_price_history() function.

conn = boto.connect_ec2(aws_key, aws_secret)
prices = conn.get_spot_price_history("m3.medium", '2017-04-20T21:14:45.000Z', '2017-04-20T21:20:45.000Z',"us-east-1")

It is giving an error

Traceback (most recent call last):
  File "run.py", line 22, in <module>
    prices = conn.get_spot_price_history("m3.medium", '2017-04-20T21:14:45.000Z', '2017-04-20T21:20:45.000Z',"us-east-1")
  File "/usr/lib/python2.6/site-packages/boto/ec2/connection.py", line 1421, in get_spot_price_history
    [('item', SpotPriceHistory)], verb='POST')
  File "/usr/lib/python2.6/site-packages/boto/connection.py", line 1182, in get_list
    raise self.ResponseError(response.status, response.reason, body)
boto.exception.EC2ResponseError: EC2ResponseError: 400 Bad Request
<?xml version="1.0" encoding="UTF-8"?>
<Response><Errors><Error><Code>InvalidRequest</Code><Message>The request received was invalid.</Message></Error></Errors><RequestID>da79e2ba-7475-4133-98f3-3c6aab8a07c6</RequestID></Response>

My aim is to get current price of an spot instance. Can anyone tell me what i am doing wrong or some other easy way/function to get spot's market value. I am new to amazon web services. Please help.

Shubham Verma
  • 129
  • 3
  • 14

3 Answers3

10

It looks like returned results are in reverse order, so the most-recent prices are returned first.

Using boto3 (which is recommended these days):

import boto3

client=boto3.client('ec2',region_name='us-east-1')

prices=client.describe_spot_price_history(InstanceTypes=['m3.medium'],MaxResults=1,ProductDescriptions=['Linux/UNIX (Amazon VPC)'],AvailabilityZone='us-east-1a')

print prices['SpotPriceHistory'][0]

Returns:

{u'Timestamp': datetime.datetime(2017, 4, 24, 20, 2, 11, tzinfo=tzlocal()),
u'ProductDescription': 'Linux/UNIX (Amazon VPC)',
u'InstanceType': 'm3.medium',
u'SpotPrice': '0.700000',
u'AvailabilityZone': 'us-east-1a'}

Please note that this does not guarantee that this is the price you would pay if you launched a matching spot instance in us-east-1a. It's merely the latest reported price for that combination.

  • On-Demand list price: $0.067
  • Latest spot price returned: $0.007 (I presume the result was in cents)
  • Spot instance pricing page was showing: $0.011
John Rotenstein
  • 241,921
  • 22
  • 380
  • 470
  • Thank you so much for the help. This is exactly what i needed. Now i can further work on my code. – Shubham Verma Apr 24 '17 at 12:38
  • Can you tell me how spot fleet gets it market price(bidding price)? Is the spot price which I'll be getting from the above code will determine that my cluster will keep on running? – Shubham Verma Apr 24 '17 at 12:41
  • The above code merely gives you the *pricing history*. The price is regularly adjusted based on supply and demand. The actual price charged is given in the [Spot Instance Data Feed](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-data-feeds.html). There is no way to know the "current" price because it can be recalculated at any time -- much like the Stock Market can only show you the most recent traded price but can't guarantee a trading price until the trade actually takes place. Also, please note that **spot fleet** pricing is calculated separately. – John Rotenstein Apr 24 '17 at 20:30
  • Spot instance pricing for each running spot instance doesn't change within each instance hour. It's frozen at the market price at the beginning of each instance hour, which may not coincide with the wall clock hour. [Source.](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-spot-instances.html) – Michael - sqlbot Apr 24 '17 at 23:27
  • Note also that `Linux/UNIX` means EC2 Classic, not VPC, if you query from an account with EC2 Classic enabled in the region, and means VPC in newer accounts. Different pricing. That may explain the price mismatch. The API should match the console. `Linux/UNIX (Amazon VPC)` is the magic string you want, there, IIRC, returns the correct pricing for all accounts. – Michael - sqlbot Apr 24 '17 at 23:31
  • When I but maxresult = 1000, I got only 168 result for type "us-east-f1", Do you know why? – Hana90 Mar 20 '18 at 07:38
  • @Hana90 Please start a new question rather than asking a via a comment on an old question. – John Rotenstein Mar 21 '18 at 07:02
  • @JohnRotenstein Ok, here is https://stackoverflow.com/questions/49400385/cant-get-max-result-of-spot-price-history-us-east-region – Hana90 Mar 21 '18 at 07:20
3

us-east-1 is a region name, get_spot_price_history accepts (optional) an availability zone. For region us-east-1, the zones are us-east-1a, us-east-1b, us-east-1c, us-east-1d, us-east-1e.

And pass the arguments as keyword arguments,

prices = conn.get_spot_price_history(instance_type="m3.medium",
                                     start_time="2017-04-20T21:14:45.000Z", 
                                     end_time="2017-04-20T21:20:45.000Z",
                                     availability_zone="us-east-1a")
franklinsijo
  • 17,784
  • 4
  • 45
  • 63
1

Get infos for all regions:

import boto3
import datetime

client = boto3.client('ec2', region_name='us-west-2')
regions = [x["RegionName"] for x in client.describe_regions()["Regions"]]

INSTANCE = "p2.xlarge"
print("Instance: %s" % INSTANCE)

results = []

for region in regions:
    client = boto3.client('ec2', region_name=region)
    prices = client.describe_spot_price_history(
        InstanceTypes=[INSTANCE],
        ProductDescriptions=['Linux/UNIX', 'Linux/UNIX (Amazon VPC)'],
        StartTime=(datetime.datetime.now() -
                   datetime.timedelta(hours=4)).isoformat(),
        MaxResults=1
    )
    for price in prices["SpotPriceHistory"]:
        results.append((price["AvailabilityZone"], price["SpotPrice"]))

for region, price in sorted(results, key=lambda x: x[1]):
    print("Region: %s price: %s" % (region, price))
delijati
  • 411
  • 5
  • 14