Developer docs menu

Seasonality and weekday patterns

Intermediate

Use weekday, monthly and daily trend data to see when a market fills up and what it charges.

Setup

This tutorial uses the jokerprice.py helper from the quickstart. Save it next to your script and set JOKERPRICE_API_KEY.

Weekday pattern

Weekend nights are Thursday and Friday in Saudi Arabia, Egypt and most of the Gulf, and Friday and Saturday in the UAE. byWeekday numbers days from 0 (Sunday) to 6 (Saturday).

Python
from jokerprice import api

DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
m = api("GET", "/api/v1/metrics", params={"city": "jeddah", "past_days": 90, "forward_days": 30})["metrics"]
for d in m["byWeekday"]:
    if d["occupancy"] is not None:
        print(f"{DAYS[d['weekday']]}  occupancy {d['occupancy']:.0%}  ADR SAR {d['adr'] or 0:.0f}  ({d['nights']} nights)")

Monthly pattern and booked-ahead months

Ask for a long window to get more months. period is observed for past months, ahead for future months (booked so far, which will rise) and mixed for the current month.

Python
m = api("GET", "/api/v1/metrics", params={"city": "jeddah", "past_days": 365, "forward_days": 180})["metrics"]
for month in m["byMonth"]:
    if month["occupancy"] is not None:
        print(month["month"], f"{month['period']:<8}", f"{month['occupancy']:.0%}", "ADR", round(month["adr"] or 0))

Daily trend series

/api/v1/trends returns one stored value per day. Each occupancy point covers the 30 nights before that day, so the line is already smoothed.

Python
t = api("GET", "/api/v1/trends", params={"city": "jeddah", "metric": "occupancy", "days": 365})["trends"]
print(t["notice"] or "")
for p in t["points"][-14:]:
    print(p["day"], f"{p['value']:.1%}", p["origin"])
for c in t["changes"]:
    print(f"vs {c['days']} days ago: {c['change']:+.1%}")

Chart it

Python
import matplotlib.pyplot as plt

days = [p["day"] for p in t["points"]]
plt.plot(days, [p["value"] for p in t["points"]])
plt.title("Jeddah occupancy, trailing 30 nights")
plt.gca().yaxis.set_major_formatter(lambda v, _: f"{v:.0%}")
plt.xticks(days[::max(1, len(days) // 8)], rotation=45)
plt.tight_layout()
plt.savefig("jeddah-occupancy.png")

Know the history you have

Monthly and daily history start when JokerPrice began tracking a destination, so early on you will see weeks, not years. Check history.days and trackingDays before comparing seasons, and expect yearOverYear to stay null until a full year is stored.