Google शीट्स मैक्रो विश्लेषक का स्क्रैचपैड हैः अद्यतन करने में तेज़, साझा करने में आसान, और पहले से ही Google कार्यक्षेत्र के बाकी हिस्सों से जुड़ा हुआ है। Google Apps Script शीट्स का अंतर्निहित जावास्क्रिप्ट रनटाइम आपको ब्राउज़र छोड़ने के बिना स्प्रेडशीट से किसी भी REST एपीआई को कॉल करने देता है। यह गाइड FXMacroData घोषणा डेटा को शीट्स टैब में खींचने के माध्यम से चलता है। UrlFetchApp, दर सीमाओं और पुनः प्रयासों को संभालने, साफ पंक्तियों में बहु-निर्देशक प्रतिक्रियाओं को सामान्य करने, और स्वचालित ताज़ा करने का शेड्यूल ताकि आपका मैक्रो डैशबोर्ड किसी भी मैनुअल हस्तक्षेप के बिना अद्यतित रहे।
आप क्या बनाएंगे
- पुनः प्रयोज्य फ़ॉच सहायक FXMacroData को के माध्यम से कॉल करता है
UrlFetchAppअंतर्निहित पुनः प्रयास और बैक-ऑफ तर्क के साथ - बहु-सूचक लोडर कई मुद्रा/संकेतक जोड़े निकालता है और प्रत्येक को एक फ्लैट स्प्रेडशीट पंक्ति में सामान्य करता है
- एक शीट्स लेखक नामित टैब बनाता है या रीसेट करता है, हेडर लिखता है, और प्रत्येक रन के साथ पंक्तियों को जोड़ता है
- समय-संचालित ट्रिगर हर सप्ताह सुबह स्वचालित रूप से ताज़ा करता है
पूर्व शर्तें
- गूगल खाता Google शीट्स और Apps Script तक पहुँच वाले किसी भी खाते
- FXMacroData एपीआई कुंजी पर साइन अप करें /अपना नाम लिखें; कई USD घोषणा अंत बिंदु प्रारंभिक परीक्षण के लिए एक कुंजी के बिना सार्वजनिक रूप से सुलभ हैं
- कोई अतिरिक्त सॉफ्टवेयर नहीं Apps Script पूरी तरह से ब्राउज़र में चलता है; कोई Node.js, पायथन, या स्थानीय टूलींग की आवश्यकता नहीं है
चरण 1
चरण 1 एक Google शीट बनाएँ और Apps स्क्रिप्ट संपादक खोलें
खुला sheets.google.com और एक नई खाली स्प्रेडशीट बनाएँ. इसे एक वर्णनात्मक नाम दें जैसे कि FXMacroData डैशबोर्ड. फिर स्क्रिप्ट संपादक खोलें:
- क्लिक करें विस्तार शीर्ष मेनू बार में।
- चुनें ऐप्स स्क्रिप्ट.
- संपादक डिफ़ॉल्ट रूप से एक नए टैब में खुलता है
Code.gsफाइल। - परियोजना का नाम बदलें (ऊपर बाएं फ़ील्ड) FXMacroData लोडर स्पष्टता के लिए।
आप यहाँ जो भी कोड लिखते हैं वह गूगल के बुनियादी ढांचे पर सर्वर-साइड पर चलता है इसमें पूरी पहुँच होती है UrlFetchApp सेवा और िकसी भी िकया जाता है िक ा िक
SpreadsheetApp सेवा।
सुझावः अपनी एपीआई कुंजी को स्क्रिप्ट गुण के रूप में स्टोर करें
कभी भी सीधे स्क्रिप्ट में अपनी एपीआई कुंजी को हार्ड कोड न करें. इसके बजाय, पर जाएं
परियोजना सेटिंग्स → स्क्रिप्ट गुण → गुण जोड़ें और एक गुण जोड़ा
FXMACRODATA_API_KEY आपकी कुंजी के साथ मान के रूप में. नीचे सहायक कार्यों के माध्यम से रनटाइम पर इस संपत्ति को पढ़ें PropertiesService.getScriptProperties(). .
- चरण 2
चरण 2 पुनः प्रयास तर्क के साथ एक फ़ेच हेल्पर लिखें
में निम्न कोड चिपकाएँ Code.gs, प्लेसहोल्डर फ़ंक्शन की जगह ले रहा है। यह सहायक लपेटता है UrlFetchApp.fetch घातीय बैक-ऑफ के साथ इसलिए क्षणिक त्रुटियों या संक्षिप्त दर सीमा प्रतिक्रियाओं पूरे रन को मार नहीं है।
/**
* Fetches a FXMacroData endpoint with automatic retry and exponential back-off.
*
* @param {string} currency - e.g. "usd", "eur", "chf"
* @param {string} indicator - e.g. "policy_rate", "gdp", "inflation"
* @returns {Object|null} - Parsed JSON response, or null on permanent failure
*/
function fetchAnnouncement(currency, indicator) {
const apiKey = PropertiesService.getScriptProperties()
.getProperty('FXMACRODATA_API_KEY') || '';
const url = `https://fxmacrodata.com/api/v1/announcements/${currency}/${indicator}`
+ (apiKey ? `?api_key=${apiKey}` : '');
const maxRetries = 4;
let delay = 1000; // 1 second initial back-off
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = UrlFetchApp.fetch(url, { muteHttpExceptions: true });
const status = response.getResponseCode();
if (status === 200) {
return JSON.parse(response.getContentText());
}
if (status === 429) {
// Rate limited — honour the back-off and retry
Logger.log(`Rate limited on attempt ${attempt}. Waiting ${delay}ms.`);
Utilities.sleep(delay);
delay *= 2; // exponential back-off
continue;
}
if (status === 404) {
Logger.log(`No data for ${currency}/${indicator} (404). Skipping.`);
return null;
}
// Other non-retryable errors
Logger.log(`HTTP ${status} for ${currency}/${indicator}.`);
return null;
} catch (e) {
Logger.log(`Network error on attempt ${attempt}: ${e.message}`);
Utilities.sleep(delay);
delay *= 2;
}
}
Logger.log(`Permanently failed after ${maxRetries} attempts: ${currency}/${indicator}`);
return null;
}
इस सहायक में कुछ बातों का ध्यान रखना चाहिए:
muteHttpExceptions: trueApps Script को गैर-200 कोड पर फेंकने से रोकता है आप स्थिति कोड प्राप्त करते हैं और तय कर सकते हैं कि क्या करना है.- HTTP 429 (बहुत सारे अनुरोध) दोहरा विलंब के साथ पुनः प्रयास को ट्रिगर करता है। FXMacroData प्रति कुंजी दर सीमाओं को लागू करता है; एक मामूली बैक-ऑफ रणनीति पूरी संकेतक स्वीप में बजट के भीतर स्क्रिप्ट रखता है।
- HTTP ४०४ सामान्यतः इसका मतलब है कि संकेतक उस मुद्रा के लिए अभी तक उपलब्ध नहीं है सहायक लौटाता है
nullतो पंक्ति साफ छोड़ दिया जाता है। Logger.logआउटपुट के तहत दिखाई देता है दृश्य → लॉग Apps Script editor में, डिबगिंग को सीधा बना रहा है.
चरण 3
चरण 3 JSON प्रतिक्रियाओं को स्प्रेडशीट पंक्तियों में सामान्य करें
FXMacroData घोषणाएं एंडपॉइंट प्रति मुद्रा/संकेतक जोड़ी एक एकल वस्तु लौटाता है. एक उपयोगी स्प्रेडशीट बनाने के लिए, आपको एक सुसंगत पंक्ति संरचना में अनुरोधों की सूची को सपाट करने की आवश्यकता है. नीचे निम्न सामान्यीकरण फ़ंक्शन जोड़ें fetchAnnouncement
/**
* Converts a FXMacroData announcement response object into a flat array
* suitable for appending as a single Sheets row.
*
* Columns: Timestamp, Currency, Indicator, Value, Prior, Consensus,
* Announcement DateTime, Direction
*
* @param {Object} data - Parsed JSON from fetchAnnouncement()
* @returns {Array} - Flat row array
*/
function toRow(data) {
if (!data) return null;
const direction =
data.val > data.prior ? 'Beat' :
data.val < data.prior ? 'Miss' : 'In line';
return [
new Date().toISOString(), // Run timestamp
(data.currency || '').toUpperCase(),
(data.indicator || '').replace(/_/g, ' '),
data.val ?? '',
data.prior ?? '',
data.consensus ?? '',
data.announcement_datetime || '',
direction
];
}
announcement_datetime FXMacroData से फ़ील्ड में दूसरे स्तर की सटीकता होती है केंद्रीय बैंक या सांख्यिकी एजेंसी ने जिस समय सटीक रीडिंग प्रकाशित की थी। यह टाइमस्टैम्प एक डुप्लिकेशन कुंजी के रूप में आदर्श हैः आप यह जांच सकते हैं कि क्या इस टाइमस्टैंप के साथ एक पंक्ति पहले से ही शीट में मौजूद है, जोड़े जाने से पहले, दोहराए गए रन पर दोहराई गई पंक्तियों को रोकता है।
के बारे में consensus क्षेत्र
सभी संकेतक एक आम सहमति/पूर्वानुमान मूल्य नहीं रखते हैं। जब यह क्षेत्र अनुपस्थित होता है तो एपीआई इसे प्रतिक्रिया वस्तु से छोड़ देता है, इसलिए data.consensus ?? '' सुरक्षित रूप से स्ट्रिंग के बजाय एक खाली सेल लिखता है "undefined". .
चरण 4
चरण 4 Google शीट्स टैब में डेटा लिखें
अब मुख्य लोडर फ़ंक्शन जोड़ें जो सब कुछ एक साथ बांधता हैः यह मुद्रा/संकेतक जोड़े की सूची पर पुनरावृत्ति करता है, कॉल करता है fetchAnnouncement, प्रत्येक परिणाम को से परिवर्तित करता है
toRow, और पंक्तियों को एक समर्पित शीट टैब में जोड़ता है।
/**
* Defines the currency/indicator pairs to track.
* Extend this list to cover additional signals for your strategy.
*/
const INDICATORS = [
{ currency: 'usd', indicator: 'policy_rate' },
{ currency: 'usd', indicator: 'inflation' },
{ currency: 'usd', indicator: 'non_farm_payrolls' },
{ currency: 'eur', indicator: 'policy_rate' },
{ currency: 'eur', indicator: 'inflation' },
{ currency: 'chf', indicator: 'gdp' },
{ currency: 'chf', indicator: 'consumer_confidence' },
{ currency: 'chf', indicator: 'gov_bond_10y' },
{ currency: 'gbp', indicator: 'policy_rate' },
{ currency: 'gbp', indicator: 'inflation' },
];
const SHEET_NAME = 'MacroData';
const HEADERS = [
'Run Timestamp', 'Currency', 'Indicator', 'Value',
'Prior', 'Consensus', 'Announcement DateTime', 'Direction'
];
/**
* Main entry point — fetches all configured indicators and
* appends new rows to the MacroData sheet tab.
*/
function loadMacroData() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
let sheet = ss.getSheetByName(SHEET_NAME);
// Create the tab if it does not exist yet
if (!sheet) {
sheet = ss.insertSheet(SHEET_NAME);
sheet.appendRow(HEADERS);
sheet.getRange(1, 1, 1, HEADERS.length)
.setFontWeight('bold')
.setBackground('#1a73e8')
.setFontColor('#ffffff');
sheet.setFrozenRows(1);
}
// Build a set of existing announcement_datetimes to avoid duplicates
const lastRow = sheet.getLastRow();
const existing = new Set();
if (lastRow > 1) {
const dtCol = 7; // "Announcement DateTime" is column 7 (index 6, 1-based col 7)
const values = sheet.getRange(2, dtCol, lastRow - 1, 1).getValues();
values.forEach(([dt]) => { if (dt) existing.add(String(dt)); });
}
const newRows = [];
INDICATORS.forEach(({ currency, indicator }) => {
// Throttle requests — 200 ms between calls keeps well within rate limits
Utilities.sleep(200);
const data = fetchAnnouncement(currency, indicator);
const row = toRow(data);
if (!row) return; // skip null / error responses
const announcementDt = row[6]; // announcement_datetime column
if (existing.has(announcementDt)) {
Logger.log(`Skipping duplicate: ${currency}/${indicator} @ ${announcementDt}`);
return;
}
newRows.push(row);
existing.add(announcementDt); // guard against duplicates within the same run
});
if (newRows.length > 0) {
sheet.getRange(sheet.getLastRow() + 1, 1, newRows.length, HEADERS.length)
.setValues(newRows);
Logger.log(`Appended ${newRows.length} new row(s) to "${SHEET_NAME}".`);
} else {
Logger.log('No new rows — all announcements already present.');
}
}
भाग जाओ। loadMacroData संपादक से मैन्युअल रूप से (क्लिक करें ▶ भागें) एक ट्रिगर सेट करने से पहले पाइपलाइन का परीक्षण करने के लिए। पहला रन आपको स्क्रिप्ट को अधिकृत करने के लिये प्रेरित करेगा क्लिक करें
समीक्षा अनुमति → अनुमति दें स्प्रेडशीट और बाहरी नेटवर्क अनुरोधों तक पहुँच प्रदान करने के लिए।
सुझावः विकास के लिए एक "रीसेट" फ़ंक्शन जोड़ें
विकास के दौरान शीट को साफ़ करना और खरोंच से फिर से चलाना उपयोगी होता है। एक छोटा सा सहायक जोड़ेंः
function resetSheet() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName(SHEET_NAME);
if (sheet) ss.deleteSheet(sheet);
loadMacroData(); // recreates with fresh headers and data
}
चरण 5
चरण 5 बड़े सूचक स्वीप के लिए दर सीमाओं को प्रबंधित करें
चरण 4 में 200 एमएस इंटर-रिसॉर्ट देरी ऊपर दिखाए गए दस संकेतक सूची के लिए पर्याप्त है। यदि आप 50 या अधिक जोड़े तक विस्तार करते हैं पूरी घोषणा कैटलॉग में कई मुद्राओं को कवर करते हैं आपको अधिक जानबूझकर थ्रॉटलिंग लागू करनी चाहिए। निरंतर नींद को काउंटर-आधारित ठहराव के साथ बदलेंः
/**
* Fetches a larger list of indicators with adaptive throttling.
* Pauses for 1 second every 10 requests to respect rate limits.
*/
function loadMacroDataBulk(indicators) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
let sheet = ss.getSheetByName(SHEET_NAME) || (() => {
const s = ss.insertSheet(SHEET_NAME);
s.appendRow(HEADERS);
s.getRange(1, 1, 1, HEADERS.length)
.setFontWeight('bold')
.setBackground('#1a73e8')
.setFontColor('#ffffff');
s.setFrozenRows(1);
return s;
})();
const newRows = [];
let count = 0;
indicators.forEach(({ currency, indicator }) => {
count++;
// Longer pause every 10 requests
if (count % 10 === 0) {
Logger.log(`Pausing after ${count} requests…`);
Utilities.sleep(1500);
} else {
Utilities.sleep(150);
}
const data = fetchAnnouncement(currency, indicator);
const row = toRow(data);
if (row) newRows.push(row);
});
if (newRows.length > 0) {
sheet.getRange(sheet.getLastRow() + 1, 1, newRows.length, HEADERS.length)
.setValues(newRows);
}
Logger.log(`Bulk load complete — ${newRows.length} rows appended.`);
}
FXMacroData घोषणा अंत बिंदु तेजी से है प्रत्येक प्रतिक्रिया आमतौर पर Google Apps स्क्रिप्ट निष्पादन वातावरण से 100 एमएस से कम में लौटती है। बड़े स्वीप पर मुख्य फ्लैट ग्लॉकेट विलंबता के बजाय प्रति कुंजी अनुरोध बजट है; के साथ कॉल की दूरी Utilities.sleep बैचिंग या कैशिंग तर्क के बिना अपनी योजना की सीमाओं के भीतर रहने के लिए सबसे सरल तरीका है।
चरण 6
चरण 6 समय-संचालित ट्रिगर के साथ स्वचालित ताज़ा करने का समय निर्धारित करें
अनुप्रयोग स्क्रिप्ट की ट्रिगर यह आपको एक समर्पित सर्वर के बिना किसी भी कार्य को एक कार्यक्रम पर चलाने देता है। निम्न सहायक एक कार्यदिवस सुबह ट्रिगर को प्रोग्राम के अनुसार बनाता है इसे एक बार संपादक से चलाकर पंजीकृत करें, फिर सहायक को स्वयं हटा दें:
/**
* Registers a time-driven trigger that runs loadMacroData()
* every weekday between 07:00 and 08:00 UTC.
*
* Run this function ONCE from the Apps Script editor to set up the trigger.
* You do not need to call it again — it persists in the project.
*/
function createWeekdayTrigger() {
// Remove any existing triggers for loadMacroData to avoid duplicates
ScriptApp.getProjectTriggers()
.filter(t => t.getHandlerFunction() === 'loadMacroData')
.forEach(t => ScriptApp.deleteTrigger(t));
ScriptApp.newTrigger('loadMacroData')
.timeBased()
.everyWeeks(1)
.onWeekDay(ScriptApp.WeekDay.MONDAY)
.atHour(7)
.create();
// Also register Tuesday through Friday
[
ScriptApp.WeekDay.TUESDAY,
ScriptApp.WeekDay.WEDNESDAY,
ScriptApp.WeekDay.THURSDAY,
ScriptApp.WeekDay.FRIDAY,
].forEach(day => {
ScriptApp.newTrigger('loadMacroData')
.timeBased()
.everyWeeks(1)
.onWeekDay(day)
.atHour(7)
.create();
});
Logger.log('Weekday triggers registered for loadMacroData.');
}
दौड़ने के बाद createWeekdayTrigger, खुला ट्रिगर (संपादक के बाएं साइडबार में अलार्म-बेल आइकन) पुष्टि करने के लिए पांच ट्रिगर दिखाई देते हैं प्रत्येक कार्यदिवस के लिए एक। प्रत्येक ट्रिजर आपके Google खाते के लिए कॉन्फ़िगर किए गए समय क्षेत्र में 07:00 और 08:00 के बीच फायर करता है।
रिलीज कैलेंडर के साथ संरेखित करना
अधिक सर्जिकल दृष्टिकोण के लिए, FXMacroData रिलीज़ कैलेंडर अंत बिंदु प्रत्येक सप्ताह की शुरुआत में उच्च प्रभाव वाली घोषणाओं के साथ दिन खोजने के लिए, फिर केवल उन दिनों पर पूर्ण संकेतक स्वीप चलाएं। इससे निष्पादन समय कम रहता है और शांत कैलेंडर सप्ताहों में एपीआई उपयोग कम होता है।
चरण 7
चरण 7 घटना के दिनों द्वारा पूर्व फ़िल्टर करने के लिए रिलीज कैलेंडर को पुनर्प्राप्त करें
/v1/calendar/{currency} endpoint किसी मुद्रा के लिए आगामी अनुसूचित रिलीज़ लौटाता है. इसे सोमवार को सप्ताह के लिए घोषणा तिथियों का एक सेट बनाने के लिए उपयोग करें, फिर बिना किसी घटना के दिनों पर fetch चरण को छोड़ दें यह शांत सप्ताहों पर अनावश्यक एपीआई कॉल से बचता है।
/**
* Returns a Set of date strings ("YYYY-MM-DD") for which at least one
* high-impact announcement is scheduled this week for the given currency.
*
* @param {string} currency - e.g. "usd"
* @returns {Set} */ फ़ंक्शन getAnnouncementDatesThisWeek(currency) { const apiKey = PropertiesService.getScriptProperties() .getProperty (('FXMACRODATA_API_KEY') '); const url = https://fxmacrodata.com/api/v1/calendar/${currency}` + (apiKey ? `(((?api_key=${apiKee}` : ' '); कन्स्ट्रो रिस्पांस = UrlFetch mute.Appfetch, {HttpExceptions: true }); if (response.getResponseCode) == 200) = new Set; fetch; const const const Date = today; fetches; const Date=newset; const {date=new); fetch.Macddata.data.forgetdate.content.text} {date = new); const const 'date' = new; const 'data.date' => 'date=now'; const 'current'; const const {data.datetime=new'; const {datetimes=now); const 'dates'; const $date=date=today); const; const (date=day); const {dates); const $data.event); const Date="date=current); const (data.today) = 'date); const) = date=date); 'date@date=last); const ('date=no'; 'date_date=present'; 'today'); const <date='); 'data=date="date="today'; 'events'; 'data@today=todays'); {date="events; 'todays; 'date="now; 'event_date_day'); } (date_today; '/'); <date="day'day'='events'); (date="/'event; 'day'eventually) '/'; 'day.date=*/' (today.date) '); '_day.day' = 'todent;'); यह फ़ंनहीं दिन का नया रिलीज़ेजेंडर है; '_नविस करने के लिए नया रिलीज करने के लिये कोई नया मैक्रो-डेट्रीज़ेशन है; {date_'
इस पैटर्न का उपयोग करने के लिए, पंजीकरण करें loadMacroDataCalendarAware के बजाय ट्रिगर हैंडलर के रूप में loadMacroData में फ़ंक्शन नाम स्ट्रिंग को बदलें createWeekdayTrigger
तदनुसार।
संक्षिप्त विवरण
सारांश
अब आपके पास एक पूर्ण, उत्पादन के लिए तैयार पाइपलाइन है जो Apps Script के माध्यम से FXMacroData को Google शीट्स से जोड़ती हैः
- पुनः प्रयास और घातीय बैक-ऑफ के साथ एक फ़ेच हेल्पर जो क्षणिक नेटवर्क त्रुटियों और दर-सीमा प्रतिक्रियाओं को उदारता से संभालता है।
- एक सामान्यीकरण कार्य जो प्रत्येक घोषणा प्रतिक्रिया को एक सुसंगत, डुप्लिकेशन-सुरक्षित स्प्रेडशीट पंक्ति में परिवर्तित करता है.
- एक शीट लेखक जो पहले रन पर हेडर बनाता है, केवल नई रिलीज़ जोड़ता है, और पहले देखा गया छोड़ देता है
announcement_datetimeमूल्य। - मुद्रा/संकेतक जोड़े के दर्जनों पार थोक स्वीप के लिए अनुकूलन थ्रॉटलिंग।
- पूर्ण स्वचालित दैनिक ताज़ा करने के लिए एक कार्यदिवस समय संचालित ट्रिगर।
- एक वैकल्पिक कैलेंडर पूर्व-जाँच जो अनुसूचित रिलीज के बिना दिनों में अतिरेक एपीआई कॉल से बचाता है.
अगला कदम
-
सूचक सूची का विस्तार पूर्ण सूची देखें
/api-data-docs
और अपनी रणनीति के लिए प्रासंगिक जोड़े जोड़ें (जैसे
chf/gov_bond_10y,eur/pmi,gbp/employment) । -
सशर्त स्वरूपण जोड़ें रेखांकित पंक्तियाँ जहाँ दिशा है
Beatहरे रंग में औरMissलाल रंग में प्रयोग किया जाता हैSpreadsheetAppConditionalFormatRuleBuilderएक नज़र में संकेत पढ़ने के लिए। -
स्लैक या ईमेल पर पुश अलर्ट पंक्तियों को जोड़ने के बाद का प्रयोग करें
MailApp.sendEmailया अंदर से वेबहुक कॉलloadMacroDataजब उच्च प्रभाव वाली छाप आती है तो अपनी टीम को सूचित करने के लिए। -
ऐतिहासिक मूल्यों का पता लगाएं
घोषणाएं अंत बिंदु
स्वीकार करता है।
start_date/end_dateपैरामीटर लाइव फ़ीड के साथ एक ऐतिहासिक टैब को बीज देने के लिए लंबी तिथि सीमा पर एक बार बैकफिल चलाएं।