Visualizing Forex Trends With Python And CurrencyFreaks Time Series API
Visualizing forex trends helps traders, analysts, and businesses understand how exchange rates actually move over time. The CurrencyFreaks Time Series API makes this easier by giving real-time and historical data. It helps you in identifying the patterns and comparing currency movements quickly. This also helps in building reports for research and budgeting.
CurrencyFreaks and PublicAPI provide developers with accurate, systematic FX data that integrates seamlessly with Python. Their endpoints provide real-time updates, time-series data, conversions, and other tools you need for deeper analysis. This makes the Time Series API a dependable choice for anyone who needs predictable and accurate data.
In this blog, you will learn how to fetch data with the CurrencyFreaks Time Series API and process it using Python. You’ll put together forex charts with Matplotlib and Plotly, following simple, step-by-step instructions. By the conclusion, you will understand how to create clear and practical visualisations from raw exchange-rate values.
Understanding CurrencyFreaks Time Series API
The CurrencyFreaks Time Series API provides historical exchange rates for a selected date range. It allows you to adjust the base currency and target currencies for daily values. It can easily track how the market moves over time. You can also compare different currency pairs side by side without getting lost in the data.
Some features in CurrencyFreaks, like extended history or large date ranges, are only available on paid plans. These limits keep the system stable but still let you run small tests on free access. You can get full historical data through the time-series API for deeper analysis using a paid plan.
A standard request looks like this:
https://api.currencyfreaks.com/v2.0/timeseries?
apikey=YOUR_API_KEY
&startDate=2024-01-01
&endDate=2024-02-01
&base=USD
&symbols=EUR,GBP,PKR
The JSON response comes with a list of dates, and each date includes the rates for all the currencies you picked in json format. CurrencyFreaks keeps the Time Series output in a simple, predictable layout, so nothing feels confusing.
Their time-series API follows the same clean structure. So Python can read it without any trouble and place everything into clear columns you can work with.
Setting Up Your Python Environment
You only need a few tools to work with the Time Series API, as the image shows. Python 3.x, requests, pandas, and Matplotlib or Plotly are enough for most workflows. You can use these tools to get the data, organize it, and turn it into clear visuals.
Install everything with a simple command:
pip install requests pandas matplotlib plotly
Store your API key in an environment variable so it does not appear directly in your script. This improves safety and keeps your repository clean. This setup allows your scripts to work reliably when using the time format.
Fetching Historical Data From CurrencyFreaks

Here is a simple example in Python for calling the CurrencyFreaks Time Series API using a request url:
import requests
import pandas as pd
import os
api_key = os.getenv("CURRENCYFREAKS_KEY")
url = "https://api.currencyfreaks.com/v2.0/timeseries"
params = {
"apikey": api_key,
"startDate": "2024-01-01",
"endDate": "2024-02-01",
"base": "USD",
"symbols": "EUR,GBP,PKR"
}
response = requests.get(url, params=params)
data = response.json()
df = pd.DataFrame(data["rates"]).T
df.index = pd.to_datetime(df.index)
This script converts the returned JSON into a DataFrame for flexible use. If a weekend or holiday has no update, you may see the same rate repeated or unchanged instead of negative values. This is normal behavior because forex markets do not generate new values during closures.
Preprocessing Data for Visualization
Once your dataset loads, turn the date index into proper Python datetime values. This keeps your Time Series data in the right order and makes the chart line up cleanly on the axis. Sorting the index keeps the chart smooth and stops the lines from looking uneven or broken.
When working with several currencies, keep all the columns in numeric format so calculations don’t break. Some actual values arrive as strings, so convert them before plotting. This makes your DataFrame more stable for real calculations, especially when you’re pulling data from a time series database API.
Optional resampling can smooth noisy lines across multiple entries for long periods. Weekly or monthly averages make broad trends easier to see in the returned data. This works well when exploring results from a time series query api or similar tools.
Visualizing Currency Trends With Matplotlib
Here is a basic Matplotlib chart using data values from the Time Series API:
import matplotlib.pyplot as plt
plt.figure(figsize=(10,5))
plt.plot(df.index, df["EUR"], label="USD → EUR")
plt.plot(df.index, df["GBP"], label="USD → GBP")
plt.plot(df.index, df["PKR"], label="USD → PKR")
plt.title("Forex Trends Using CurrencyFreaks Time Series API")
plt.xlabel("Date")
plt.ylabel("Exchange Rate")
plt.legend()
plt.grid(True)
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
Matplotlib is one of the best choices when you just want a clean, static chart for a report or dashboard. It keeps things simple and predictable. If you want to zoom in, hover over points, or play with interactive layers, then Plotly fits that kind of work better.
Visualizing Forex Trends With Plotly (Interactive)
Plotly adds interactive controls to your Time Series API results. These features help you inspect individual points, zoom into periods, or highlight sudden movements. This can be useful when studying trends for deeper market events.
Here is following example using Plotly Express:
import plotly.express as px
fig = px.line(df, x=df.index, y=["EUR","GBP","PKR"],
title="Interactive Forex Chart Using Time Series API")
fig.update_xaxes(title="Date")
fig.update_yaxes(title="Exchange Rate")
fig.show()
You can add small notes to highlight important moments or export the chart as an HTML file if you want to share it. This approach also fits nicely when you're building dashboards that talk to a time series Python API or through a time series REST API. It helps people read the data more easily because the trends stand out right away.
Use Cases & Practical Applications
Forex analysts use the Time Series API to understand how currencies respond to world events. They compare long periods to see how stable or volatile a pair has been. These visuals help guide trading choices and risk management.
Businesses use this data to adjust product pricing for international suppliers. Small shifts in exchange rates affect costs for imports and exports. With the Time Series API, companies can prepare budgets based on realistic historical behavior across each time interval.
Finance teams often set up weekly or daily snapshots to keep things updated. These snapshots make it easier to watch spending and revenue in different countries. Many dashboards pair this with a real-time time series API or a time series forecasting API to help predict what might happen next.

How to Visualize Currency Trends Using CurrencyFreaks API?
Step 1: Install Required Packages
Make sure Python is installed on your system. Then install the required packages:
pip install requests pandas
These packages are used for:
-
Making API requests
-
Processing and formatting data
Step 2: Create the Python File
Create a new Python file, for example:
forex_timeseries.py
Step 3: Add Required Imports
import requests
import pandas as pd
import webbrowser
import os
import json
Step 4: Configure the API
Add your CurrencyFreaks API key, endpoints, and basic settings:
API_KEY = "YOUR_API_KEY"
URL = "https://api.currencyfreaks.com/v2.0/timeseries"
CURRENCY_SYMBOLS_URL = "https://api.currencyfreaks.com/v2.0/currency-symbols"
Step 5: Define Allowed Currencies
Only these currencies will appear in the dropdown:
ALLOWED_SYMBOLS = {
"AGLD": "Austral Gold Ltd",
"FJD": "Fiji Dollar",
"MXN": "Mexican Peso",
"SCR": "Seychellois Rupee",
"CDF": "Congolese Franc",
"BBD": "Barbadian Dollar",
"HNL": "Honduran Lempira",
"UGX": "Uganda Shilling",
"PKR": "Pakistani Rupee",
"EUR": "Euro",
"GBP": "Pound Sterling",
"CAD": "Canadian Dollar",
"USD": "US Dollar",
"ETH": "Ethereum",
}
Step 6: Set API Parameters
PARAMS = {
"apikey": API_KEY,
"startDate": "2024-01-01",
"endDate": "2024-12-31",
"base": "USD",
"symbols": "USD,GBP,PKR,AGLD,FJD,MXN,SCR,CDF,BBD,HNL,UGX,EUR,GBP,CAD,USD,ETH"
}
HTML_FILE = "forex_timeseries_table.html"
Step 7: Fetch Time Series Data
def fetch_timeseries_data():
response = requests.get(URL, params=PARAMS)
if response.status_code != 200:
raise Exception(f"API Error: {response.text}")
return response.json()
Step 8: Fetch Currency Symbols
def fetch_currency_symbols():
response = requests.get(CURRENCY_SYMBOLS_URL, params={"apikey": API_KEY})
if response.status_code != 200:
raise Exception(f"Currency Symbols API Error: {response.text}")
data = response.json()
api_symbols = data.get("currencySymbols", {})
return {code: api_symbols.get(code, name) for code, name in ALLOWED_SYMBOLS.items()}
Step 9: Process API Data
def process_data(api_data):
rows = []
for item in api_data["historicalRatesList"]:
row = {"Date": item["date"]}
for currency, value in item["rates"].items():
row[currency] = float(value)
rows.append(row)
df = pd.DataFrame(rows)
df["Date"] = pd.to_datetime(df["Date"])
df.sort_values("Date", inplace=True)
return df
Step 10: Generate HTML and Charts
This step creates the interactive HTML page using Chart.js.
def generate_html_table(df, currencysymbols):
dates = df["Date"].dt.strftime("%Y-%m-%d").tolist()
series = {col: df[col].tolist() for col in df.columns if col != "Date"}
data_json = json.dumps({"dates": dates, "series": series})
dropdown_options = "\n".join([
f'<option value="{code}">{code}</option>' for code in sorted(ALLOWED_SYMBOLS.keys())
])
html_content = f"""
<!-- HTML + Chart.js content -->
"""
with open(HTML_FILE, "w", encoding="utf-8") as file:
file.write(html_content)
Step 11: Main Function
def main():
api_data = fetch_timeseries_data()
currency_symbols = fetch_currency_symbols()
df = process_data(api_data)
generate_html_table(df, currency_symbols)
file_path = os.path.abspath(HTML_FILE)
webbrowser.open(f"file:///{file_path}")
if name == "__main__":
main()
Step 12: Run the Script
Run the script:
python forex_timeseries.py
Complete Code
import requests
import pandas as pd
import webbrowser
import os
import json
# =========================
# CONFIG
# =========================
API_KEY = "c0cf4c51f1424ef483b76cbf83592864"
URL = "https://api.currencyfreaks.com/v2.0/timeseries"
CURRENCY_SYMBOLS_URL = "https://api.currencyfreaks.com/v2.0/currency-symbols"
# Only show these symbols in dropdown
ALLOWED_SYMBOLS = {
"AGLD": "",
"FJD": "Fiji Dollar",
"MXN": "Mexican Peso",
"SCR": "Seychellois Rupee",
"CDF": "Congolese Franc",
"BBD": "Barbadian Dollar",
"HNL": "Honduran Lempira",
"UGX": "Uganda Shilling",
"PKR": "Pakistani Rupee",
"EUR": "Euro",
"GBP": "Pound Sterling",
"CAD": "Canadian Dollar",
"USD": "US Dollar",
"ETH": "Ethereum",
}
PARAMS = {
"apikey": API_KEY,
"startDate": "2024-01-01",
"endDate": "2024-12-31",
"base": "USD",
"symbols": "USD,GBP,PKR,AGLD,FJD,MXN,SCR,CDF,BBD,HNL,UGX,EUR,GBP,CAD,USD,ETH"
}
HTML_FILE = "forex_timeseries_table.html"
# =========================
# FETCH DATA
# =========================
def fetch_timeseries_data():
response = requests.get(URL, params=PARAMS)
if response.status_code != 200:
raise Exception(f"API Error: {response.text}")
return response.json()
def fetch_currency_symbols():
"""
Fetch available currency symbols for dropdown.
"""
response = requests.get(CURRENCY_SYMBOLS_URL, params={"apikey": API_KEY})
if response.status_code != 200:
raise Exception(f"Currency Symbols API Error: {response.text}")
data = response.json()
api_symbols = data.get("currencySymbols", {})
# Restrict to allowed symbols; fallback to allowed list even if API missing
filtered = {code: api_symbols.get(code, name) for code, name in ALLOWED_SYMBOLS.items()}
return filtered
# =========================
# PROCESS DATA
# =========================
def process_data(api_data):
rows = []
for item in api_data["historicalRatesList"]:
row = {"Date": item["date"]}
for currency, value in item["rates"].items():
row[currency] = float(value)
rows.append(row)
df = pd.DataFrame(rows)
df["Date"] = pd.to_datetime(df["Date"])
df.sort_values("Date", inplace=True)
return df
# =========================
# GENERATE HTML
# =========================
def generate_html_table(df, _currency_symbols):
# Data for charts (dates + series per currency)
dates = df["Date"].dt.strftime("%Y-%m-%d").tolist()
series = {col: df[col].tolist() for col in df.columns if col != "Date"}
data_payload = {"dates": dates, "series": series}
data_json = json.dumps(data_payload)
# Dropdown options: show all allowed symbols (short code only)
available_currencies = sorted(ALLOWED_SYMBOLS.keys())
dropdown_options = "\n".join(
[f'<option value="{code}">{code}</option>' for code in available_currencies]
)
min_date = dates[0] if dates else ""
max_date = dates[-1] if dates else ""
html_content = f"""
<html>
<head>
<title>Forex Time Series Charts</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
body {{
font-family: "Segoe UI", Tahoma, sans-serif;
background: linear-gradient(135deg, #f5f7fa, #e4ecf7);
padding: 30px;
}}
h2 {{
text-align: center;
color: #2c3e50;
margin-bottom: 25px;
letter-spacing: 0.5px;
}}
.controls {{
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
margin-bottom: 14px;
flex-wrap: wrap;
}}
.controls label {{
font-weight: 600;
color: #1f2937;
}}
select,
input[type="date"] {{
padding: 6px 8px;
border-radius: 8px;
border: 1px solid #cbd5e1;
background-color: #ffffff;
font-size: 13px;
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.04);
min-width: 140px;
}}
.chart-card {{
margin-top: 24px;
background: #fff;
border-radius: 12px;
padding: 20px;
box-shadow: 0 10px 30px rgba(0,0,0,0.08);
}}
</style>
</head>
<body>
<h2>Forex Time Series Data (Base: {PARAMS["base"]})</h2>
<div class="controls">
<label for="currency-dropdown">Currencies:</label>
<select id="currency-dropdown" name="currency">
<option value="" disabled selected>Select currency</option>
{dropdown_options}
</select>
<label for="start-date">Start Date:</label>
<input type="date" id="start-date" name="start-date" value="">
<label for="end-date">End Date:</label>
<input type="date" id="end-date" name="end-date" value="">
<label for="chart-type">Chart:</label>
<select id="chart-type" name="chart-type">
<option value="" disabled selected>Select chart</option>
<option value="bar">Bar Chart</option>
<option value="line">Line Graph</option>
</select>
</div>
<div class="chart-card">
<canvas id="chartCanvas" height="120"></canvas>
</div>
<script>
const dataPayload = {data_json};
const currencySelect = document.getElementById('currency-dropdown');
const chartTypeSelect = document.getElementById('chart-type');
const startDateInput = document.getElementById('start-date');
const endDateInput = document.getElementById('end-date');
const ctx = document.getElementById('chartCanvas').getContext('2d');
let chartInstance = null;
function renderChart() {{
const currency = currencySelect.value;
const chartType = chartTypeSelect.value;
const allDates = dataPayload.dates;
const allValues = dataPayload.series[currency] || [];
if (!currency || !chartType || !startDateInput.value || !endDateInput.value) {{
if (chartInstance) {{
chartInstance.destroy();
}}
return;
}}
const start = startDateInput.value;
const end = endDateInput.value;
// Filter by selected date range
const filteredDates = [];
const filteredValues = [];
allDates.forEach((d, idx) => {{
if (d >= start && d <= end) {{
filteredDates.push(d);
filteredValues.push(allValues[idx]);
}}
}});
if (chartInstance) {{
chartInstance.destroy();
}}
if (chartType === 'line') {{
chartInstance = new Chart(ctx, {{
type: 'line',
data: {{
labels: filteredDates,
datasets: [{{
label: currency + ' Rates',
data: filteredValues,
backgroundColor: 'rgba(99, 102, 241, 0.2)',
borderColor: 'rgba(99, 102, 241, 1)',
borderWidth: 2,
fill: false,
tension: 0.1
}}]
}},
options: {{
responsive: true,
scales: {{
x: {{ title: {{ display: true, text: 'Date' }} }},
y: {{ title: {{ display: true, text: 'Rate' }}, beginAtZero: false }}
}}
}}
}});
}} else {{
chartInstance = new Chart(ctx, {{
type: 'bar',
data: {{
labels: filteredDates,
datasets: [{{
label: currency + ' Rates',
data: filteredValues,
backgroundColor: 'rgba(16, 185, 129, 0.6)',
borderColor: 'rgba(16, 185, 129, 1)',
borderWidth: 1
}}]
}},
options: {{
responsive: true,
scales: {{
x: {{ title: {{ display: true, text: 'Date' }} }},
y: {{ title: {{ display: true, text: 'Rate' }}, beginAtZero: false }}
}}
}}
}});
}}
}}
currencySelect.addEventListener('change', renderChart);
chartTypeSelect.addEventListener('change', renderChart);
startDateInput.addEventListener('change', renderChart);
endDateInput.addEventListener('change', renderChart);
renderChart();
</script>
</body>
</html>
"""
with open(HTML_FILE, "w", encoding="utf-8") as file:
file.write(html_content)
# =========================
# MAIN
# =========================
def main():
print("Fetching forex data...")
api_data = fetch_timeseries_data()
print("Fetching currency symbols for dropdown...")
currency_symbols = fetch_currency_symbols()
print("Processing data...")
df = process_data(api_data)
print("Generating HTML table...")
generate_html_table(df, currency_symbols)
file_path = os.path.abspath(HTML_FILE)
print(f"Opening table in browser: {file_path}")
webbrowser.open(f"file:///{file_path}")
# =========================
# RUN SCRIPT
# =========================
if __name__ == "__main__":
main()
Step 13: How to Use the Application
Once the HTML page opens in your browser, you can interact with the chart using the controls at the top:
-
Select Currency: Choose a currency from the dropdown (for example: USD, PKR, EUR, GBP).
-
Select Start Date: Pick the starting date for the data you want to view.
-
Select End Date: Pick the ending date for the selected range.
-
Select Chart Type: Choose whether you want to view the data as a Line Graph or a Bar Chart.


Common Pitfalls & Best Practices
CurrencyFreaks sets limits for free plans. So heavy use of the Time Series API may require an upgrade when each request goes beyond a single value.
Larger requests or wide ranges often need a professional tier. This ensures stable performance when fetching long histories.
Missing values should always be checked, especially when working with a time series data API. Gaps appear during weekends, holidays, or low-activity days. Use interpolation or forward-fill if your model needs consistent sequences.
Avoid clutter when plotting many currencies at once across multiple datasets. Too many overlapping lines make patterns hard to read. Consider subplots or multiple charts when using a time series insights api or stock time series data api.
Conclusion
You learned how to pull historical forex data points with the CurrencyFreaks Time Series API, process it in Python, and turn it into clear charts with Matplotlib and Plotly. This makes trends easier to spot and helps you use the data for research or everyday decisions.
Try experimenting with broader time ranges or additional currencies. Add annotations for economic events or export charts for reporting. The Time Series API gives you stable input data, so your Python tools stay predictable.
You can set your visuals to update on their own or drop them into a dashboard. You can also connect this workflow with other analytics tools if you want to dig a little deeper. It gives you a simple, clear way to keep an eye on how currencies shift.
FAQs
What Is The Time Series Endpoint In CurrencyFreaks API?
The Time Series endpoint gives you daily exchange rates for any range you choose. You set the base currency, pick the currencies you want to compare, and it returns all the numbers you need for your analysis.
How Far Back Does CurrencyFreaks Historical Data Go?
CurrencyFreaks provides historical values going back to 1984 for many currencies. The range depends on the currency pair. Older data helps users explore long-term behavior.
Do I Need A Paid Plan To Use Time Series Or Historical Data?
Some features of CurrencyFreaks are only available on paid plans. Bigger date ranges and heavier requests usually fall in the higher tiers. This keeps services running smoothly and consistently, especially when you’re sending a lot of requests.
Can I Compare Multiple Currency Pairs In One Chart?
Yes, you can pull multiple symbols in a single request. Showing them on the same chart makes the comparison easier. Subplots help if you want a cleaner view.
Should I Use Matplotlib Or Plotly For Forex Trend Visualization?
Use Matplotlib when you just need a clean, static chart for a quick report. Use Plotly when you want something interactive or a bit more visual. Both pairs easily work with the Time Series API.
How Do I Handle Missing Or Irregular Data?
You can sort, resample, or interpolate values. Gaps often appear due to weekends or holidays. Clear preprocessing improves chart accuracy.
Try the CurrencyFreaks Time Series API and turn raw exchange rates into clear insights you can actually use.
