如何使用FXMacroData API banner image

Implementation

How-To Guides

如何使用FXMacroData API

一个步骤指南,从Go调用FXMacroData REST API,涵盖net/http客户端设置,查询参数身份验证,JSON解码,以及可重复使用的助手,发布日历和FX现货价格.

其他语言版本 English

围棋是金融工具的热门工具. 由于其快速编译,可预测的性能和一流的并发原始特性,它非常适合数据管道和交易自动化. 本指南介绍了您需要调用Go的FXMacroData REST API的所有内容,从简单的一次性请求到可重复使用的客户端,可处理时间过剩,JSON解码和可选日期过. 到最后,您将拥有语义上的围棋代码,可以获取宏指标公告,拉出即将发布的日历,并查询FX现货率.

你将要建造什么

一个轻量级的Go HTTP客户端,使用查询参数API键验证对 FXMacroData REST API进行验证,将结构化的JSON响应解码为类型的Go结构,并为三大最常见的终端端家庭暴露可重复使用的辅助函数:公告,发布日历和FX现货率.

预先要求

  • 已安装了G 1.21或更高版本 (现在可以使用) 没有
  • 一个FXMacroData API 键 登录 订阅 接收一个
  • 基本熟悉Go模块和标准库

没有第三方HTTP或JSON库需要标准 net/http 现在我 encoding/json 包裹处理一切.

步骤1 了解API的形状

每个FXMacroData指标终点都遵循相同的URL模式:

GET https://fxmacrodata.com/api/v1/announcements/{currency}/{indicator}?api_key=YOUR_API_KEY

响应是一个JSON对象, data 每个元素都包含一个 date 字符串,一个数字. val选择性地提供 announcement_datetime 这样可以确定数字何时正式发布.

curl "https://fxmacrodata.com/api/v1/announcements/usd/wages?api_key=YOUR_API_KEY&start=2024-01-01"
{
  "data": [
    { "date": "2025-03-14", "val": 4.0, "announcement_datetime": "2025-03-14T12:30:00Z" },
    { "date": "2025-02-07", "val": 4.1, "announcement_datetime": "2025-02-07T13:30:00Z" },
    { "date": "2025-01-10", "val": 3.9, "announcement_datetime": "2025-01-10T13:30:00Z" }
  ]
}

同样的封面结构适用于日历和外汇终端,使得写一个通用解码器和专门的每个终端类型更容易.

步骤2 启动您的模块

创建一个新的目录,并启动一个Go模块:

mkdir fxmd-go && cd fxmd-go
go mod init fxmd

存储您的API密钥在环境变量中,而不是硬编码它.您可以将其出口到当前的 shell 会议:

export FXMD_API_KEY="your_actual_api_key_here"

安全提示

永远不要将API密钥硬编码到源文件中,也不要将其提交到版本控制中.在生产中使用秘密管理器或CI/CD环境变量.这里显示的模式在启动时读取密钥,如果变量缺失,则会很快失败.

步骤3 确定应对类型

创建一个名为 fxmd.go. 首先定义 Go 结构,将其映射到您将使用的三个终点家族返回的 JSON 形状:

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
	"time"
)

const baseURL = "https://fxmacrodata.com/api/v1"

// DataPoint represents a single indicator observation.
type DataPoint struct {
	Date                string  `json:"date"`
	Val                 float64 `json:"val"`
	AnnouncementDatetime string  `json:"announcement_datetime,omitempty"`
}

// AnnouncementsResponse is the envelope for indicator announcement endpoints.
type AnnouncementsResponse struct {
	Data []DataPoint `json:"data"`
}

// CalendarEvent represents one upcoming or recent release on the calendar.
type CalendarEvent struct {
	Date      string  `json:"date"`
	Indicator string  `json:"indicator"`
	Expected  float64 `json:"expected,omitempty"`
	Prior     float64 `json:"prior,omitempty"`
	Actual    float64 `json:"actual,omitempty"`
}

// CalendarResponse is the envelope for the release calendar endpoint.
type CalendarResponse struct {
	Data []CalendarEvent `json:"data"`
}

// ForexPoint represents a single FX spot-rate observation.
type ForexPoint struct {
	Date string  `json:"date"`
	Rate float64 `json:"rate"`
}

// ForexResponse is the envelope for the FX spot-rate endpoint.
type ForexResponse struct {
	Data []ForexPoint `json:"data"`
}

步骤4 建立可重复使用的客户端

周围是薄薄的包裹. net/http 客户端在构建时读取API键一次,在每个请求中注入它作为查询参数,并强制执行时间止,因此慢的上游永远无法无限期停滞你的程序:

// Client is a lightweight FXMacroData API client.
type Client struct {
	apiKey     string
	httpClient *http.Client
}

// NewClient creates a Client that reads the API key from the FXMD_API_KEY environment variable.
// It panics at startup if the variable is not set — fail-fast is safer than silent empty results.
func NewClient() *Client {
	key := os.Getenv("FXMD_API_KEY")
	if key == "" {
		panic("FXMD_API_KEY environment variable is not set")
	}
	return &Client{
		apiKey: key,
		httpClient: &http.Client{
			Timeout: 15 * time.Second,
		},
	}
}

// get performs a GET request to the given path with optional query parameters.
// It decodes the JSON body into dest.
func (c *Client) get(path string, params url.Values, dest any) error {
	if params == nil {
		params = url.Values{}
	}
	params.Set("api_key", c.apiKey)

	u := baseURL + path + "?" + params.Encode()
	resp, err := c.httpClient.Get(u)
	if err != nil {
		return fmt.Errorf("http get %s: %w", path, err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		return fmt.Errorf("api error %d on %s: %s", resp.StatusCode, path, body)
	}

	if err := json.NewDecoder(resp.Body).Decode(dest); err != nil {
		return fmt.Errorf("json decode %s: %w", path, err)
	}
	return nil
}

使用 json.NewDecoder 在响应体上 (而不是首先读取体到字节片段) 是Go的语法方法:它直接从HTTP连接中流出解码,避免对大型有效载荷进行中间分配.

步骤 5 添加每一个终点家庭的打字助手

包装通用药 get 通过打字辅助器,使得调用者不必手动构建路径或解码信封:

// GetAnnouncements retrieves indicator announcement data for the given currency and indicator slug.
// start and end are optional date strings in "YYYY-MM-DD" format; pass "" to omit them.
//
// Example: client.GetAnnouncements("usd", "wages", "2024-01-01", "")
// Full indicator catalogue: https://fxmacrodata.com/api-data-docs/usd/wages
func (c *Client) GetAnnouncements(currency, indicator, start, end string) (*AnnouncementsResponse, error) {
	params := url.Values{}
	if start != "" {
		params.Set("start", start)
	}
	if end != "" {
		params.Set("end", end)
	}
	var out AnnouncementsResponse
	err := c.get("/announcements/"+currency+"/"+indicator, params, &out)
	return &out, err
}

// GetCalendar retrieves the upcoming release calendar for the given currency code.
//
// Example: client.GetCalendar("usd")
func (c *Client) GetCalendar(currency string) (*CalendarResponse, error) {
	var out CalendarResponse
	err := c.get("/calendar/"+currency, nil, &out)
	return &out, err
}

// GetForex retrieves FX spot-rate history for a currency pair.
// start and end are optional date strings in "YYYY-MM-DD" format.
//
// Example: client.GetForex("eur", "usd", "2024-01-01", "")
func (c *Client) GetForex(base, quote, start, end string) (*ForexResponse, error) {
	params := url.Values{}
	if start != "" {
		params.Set("start", start)
	}
	if end != "" {
		params.Set("end", end)
	}
	var out ForexResponse
	err := c.get("/forex/"+base+"/"+quote, params, &out)
	return &out, err
}

步骤6 把它全部连接起来 main

通过客户端和助手,调用API简洁,安全. main 功能到 fxmd.go 实践所有三个终点组:

func main() {
	client := NewClient()

	// --- Announcements: US wages ---
	fmt.Println("=== US Wages (last 5 releases) ===")
	wages, err := client.GetAnnouncements("usd", "wages", "2024-01-01", "")
	if err != nil {
		fmt.Println("error:", err)
	} else {
		for i, pt := range wages.Data {
			if i >= 5 {
				break
			}
			fmt.Printf("  %s  val=%.2f  released=%s\n", pt.Date, pt.Val, pt.AnnouncementDatetime)
		}
	}

	// --- Release calendar: upcoming USD events ---
	fmt.Println("\n=== Upcoming USD Releases ===")
	cal, err := client.GetCalendar("usd")
	if err != nil {
		fmt.Println("error:", err)
	} else {
		for i, ev := range cal.Data {
			if i >= 5 {
				break
			}
			fmt.Printf("  %s  %s  prior=%.2f  expected=%.2f\n",
				ev.Date, ev.Indicator, ev.Prior, ev.Expected)
		}
	}

	// --- FX spot rates: EUR/USD ---
	fmt.Println("\n=== EUR/USD Spot Rate (last 5 days) ===")
	fx, err := client.GetForex("eur", "usd", "2025-01-01", "")
	if err != nil {
		fmt.Println("error:", err)
	} else {
		for i, pt := range fx.Data {
			if i >= 5 {
				break
			}
			fmt.Printf("  %s  rate=%.5f\n", pt.Date, pt.Rate)
		}
	}
}

运行程序:

go run fxmd.go

你应该看到类似于:

=== US Wages (last 5 releases) ===
  2025-03-14  val=4.00  released=2025-03-14T12:30:00Z
  2025-02-07  val=4.10  released=2025-02-07T13:30:00Z
  2025-01-10  val=3.90  released=2025-01-10T13:30:00Z
  2024-12-06  val=4.00  released=2024-12-06T13:30:00Z
  2024-11-01  val=4.00  released=2024-11-01T12:30:00Z

=== Upcoming USD Releases ===
  2025-04-25  gdp  prior=2.30  expected=0.40
  2025-05-02  non_farm_payrolls  prior=228.00  expected=135.00
  2025-05-13  inflation  prior=2.40  expected=2.30

=== EUR/USD Spot Rate (last 5 days) ===
  2025-04-17  rate=1.13452
  2025-04-16  rate=1.13680
  2025-04-15  rate=1.13590
  2025-04-14  rate=1.13320
  2025-04-11  rate=1.13580

提示 随着小程序的同时取出

由于客户端是安全的同时使用, 您可以使用 goroutines 和 sync.WaitGroup 没有 errgroup墙时钟时间保持在最慢单一请求的延迟附近,而不是所有请求的总和.

步骤7 处理页面化和日期范围

默认情况下,公告终点返回所有可用历史. 货币供应量 没有 国内生产总值 您通常会想限制使用窗口的时间. start 现在我 end 两个辅助器都支持它们. 这里是一个集中示例,只取出最近的四分之一. 美国兼职 数据:

// Fetch US part-time employment for the last 90 days
end := time.Now().Format("2006-01-02")
start := time.Now().AddDate(0, 0, -90).Format("2006-01-02")

pt, err := client.GetAnnouncements("usd", "part_time_employment", start, end)
if err != nil {
    log.Fatal(err)
}
for _, dp := range pt.Data {
    fmt.Printf("%s  %.0f\n", dp.Date, dp.Val)
}

现在我们要去做什么? time 包装格式日期为 "2006-01-02" (参考时间是记忆:02月01日03:40:5 PM'06-0700),与API所期望的ISO-8601日期字符串相匹配.

第8步 解析 announcement_datetime 作为一个 time.Time

没有什么. announcement_datetime 字符串是UTC RFC-3339字符. 如果您的应用程序需要计算发布时间倒计时,排序事件或按会话排序数据,请将其解析为 time.Time 值:

const rfc3339 = time.RFC3339

for _, dp := range wages.Data {
    if dp.AnnouncementDatetime == "" {
        continue
    }
    t, err := time.Parse(rfc3339, dp.AnnouncementDatetime)
    if err != nil {
        log.Printf("bad datetime %q: %v", dp.AnnouncementDatetime, err)
        continue
    }
    until := time.Until(t)
    fmt.Printf("%s  val=%.2f  in %s\n", dp.Date, dp.Val, until.Round(time.Minute))
}

完整的文件列表

参考,以下是上面的步骤中描述的完整单文件实现:

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
	"time"
)

const baseURL = "https://fxmacrodata.com/api/v1"

type DataPoint struct {
	Date                string  `json:"date"`
	Val                 float64 `json:"val"`
	AnnouncementDatetime string  `json:"announcement_datetime,omitempty"`
}

type AnnouncementsResponse struct {
	Data []DataPoint `json:"data"`
}

type CalendarEvent struct {
	Date      string  `json:"date"`
	Indicator string  `json:"indicator"`
	Expected  float64 `json:"expected,omitempty"`
	Prior     float64 `json:"prior,omitempty"`
	Actual    float64 `json:"actual,omitempty"`
}

type CalendarResponse struct {
	Data []CalendarEvent `json:"data"`
}

type ForexPoint struct {
	Date string  `json:"date"`
	Rate float64 `json:"rate"`
}

type ForexResponse struct {
	Data []ForexPoint `json:"data"`
}

type Client struct {
	apiKey     string
	httpClient *http.Client
}

func NewClient() *Client {
	key := os.Getenv("FXMD_API_KEY")
	if key == "" {
		panic("FXMD_API_KEY environment variable is not set")
	}
	return &Client{
		apiKey: key,
		httpClient: &http.Client{Timeout: 15 * time.Second},
	}
}

func (c *Client) get(path string, params url.Values, dest any) error {
	if params == nil {
		params = url.Values{}
	}
	params.Set("api_key", c.apiKey)
	u := baseURL + path + "?" + params.Encode()
	resp, err := c.httpClient.Get(u)
	if err != nil {
		return fmt.Errorf("http get %s: %w", path, err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		return fmt.Errorf("api error %d on %s: %s", resp.StatusCode, path, body)
	}
	return json.NewDecoder(resp.Body).Decode(dest)
}

func (c *Client) GetAnnouncements(currency, indicator, start, end string) (*AnnouncementsResponse, error) {
	params := url.Values{}
	if start != "" { params.Set("start", start) }
	if end != ""   { params.Set("end",   end)   }
	var out AnnouncementsResponse
	return &out, c.get("/announcements/"+currency+"/"+indicator, params, &out)
}

func (c *Client) GetCalendar(currency string) (*CalendarResponse, error) {
	var out CalendarResponse
	return &out, c.get("/calendar/"+currency, nil, &out)
}

func (c *Client) GetForex(base, quote, start, end string) (*ForexResponse, error) {
	params := url.Values{}
	if start != "" { params.Set("start", start) }
	if end != ""   { params.Set("end",   end)   }
	var out ForexResponse
	return &out, c.get("/forex/"+base+"/"+quote, params, &out)
}

func main() {
	client := NewClient()

	wages, err := client.GetAnnouncements("usd", "wages", "2024-01-01", "")
	if err != nil {
		fmt.Println("wages error:", err)
	} else {
		fmt.Println("=== US Wages ===")
		for i, pt := range wages.Data {
			if i >= 5 { break }
			fmt.Printf("  %s  %.2f\n", pt.Date, pt.Val)
		}
	}

	cal, err := client.GetCalendar("usd")
	if err != nil {
		fmt.Println("calendar error:", err)
	} else {
		fmt.Println("=== Upcoming USD Releases ===")
		for i, ev := range cal.Data {
			if i >= 5 { break }
			fmt.Printf("  %s  %s\n", ev.Date, ev.Indicator)
		}
	}

	fx, err := client.GetForex("eur", "usd", "2025-01-01", "")
	if err != nil {
		fmt.Println("forex error:", err)
	} else {
		fmt.Println("=== EUR/USD ===")
		for i, pt := range fx.Data {
			if i >= 5 { break }
			fmt.Printf("  %s  %.5f\n", pt.Date, pt.Rate)
		}
	}
}

接下来是什么?

现在您有一个可用的Go客户端,涵盖了三个最常见的FXMacroData终端端.

  • 扩大结构定义 捕获其他领域,如 revised 值从日历终点.
  • 加入一个 errgroup基于风扇的 获取多种货币同时 Client 由于 http.Client 设计上是安全的.
  • 持续结果到本地 SQLite 数据库 使用 database/sql 对于轻量级的后验或信号研究.
  • 查看指标的全部目录 美元的 工资资格 其他货币在仪表板上查看 其他没有人知道. 兼职工作没有 国内生产总值 根据这份指南的需求信号,

AI Answer-Ready

Key Facts

Page
How To Use The FXmacrodata API With Go
Section
Articles
Canonical URL
https://fxmacrodata.com/articles/how-to-use-the-fxmacrodata-api-with-go
Source
FXMacroData editorial and official publisher references
Last Updated
2026-04-22 12:36 UTC

Provenance And Trust

Cite the canonical URL and source field above. Where available, this page maps to official publisher releases and timestamped updates.

Quick Q&A

What is this page about? This page explains How To Use The FXmacrodata API With Go with directly usable context for trading, research, and API workflows.

What source should be cited? Use the canonical URL and the listed source field; cite official publisher references when available.

How fresh is this content? The last updated value above reflects the page metadata or latest available data timestamp.

Can this be used in AI assistants? Yes. This section is intentionally structured for retrieval and citation in chat assistants.

Prompt Packs

Use these in ChatGPT, Claude, Gemini, Mistral, Perplexity, or Grok for consistent source-aware outputs.

Blogroll