Why a Spreadsheet Trading Journal?
Most traders know they should keep a journal but find it tedious. The solution: automate the data collection. When you log a trade, the sheet automatically fetches the indicator state at entry, calculates R-multiples, and updates your performance dashboard.
Google Sheets with Apps Script can call the TickAtlas API directly. No server needed, no deployment -- just a spreadsheet that gets smarter over time.
Sheet Structure
Set up three tabs:
Trades
Columns: Date, Symbol, Direction, Entry, Stop Loss, Take Profit, Exit, P/L, R-Multiple, RSI at Entry, MACD at Entry, Notes
Dashboard
Win rate, average R, profit factor, max drawdown, equity curve chart, best/worst pairs
Live Prices
Auto-refreshing current prices and indicator values for your watchlist
Apps Script: Fetching Indicator Data
Open your Google Sheet, go to Extensions > Apps Script, and add this code:
const API_KEY = "YOUR_API_KEY";
const BASE_URL = "https://tickatlas.com/v1";
/**
* Fetch a technical indicator value.
* Usage: =CLAW_INDICATOR("EURUSD", "RSI_14", "H4")
*/
function CLAW_INDICATOR(symbol, indicator, timeframe) {
const url = \`\${BASE_URL}/indicator?symbol=\${symbol}\` +
\`&indicator=\${indicator}&timeframe=\${timeframe}\ Auto-Fill Indicators on Trade Entry
/**
* When a new trade is logged, auto-fill indicator columns.
* Triggered by an onEdit event on the Trades sheet.
*/
function onTradeEntry(e) {
const sheet = e.source.getActiveSheet();
if (sheet.getName() !== "Trades") return;
const row = e.range.getRow();
const col = e.range.getColumn();
// Column B = Symbol (trigger when symbol is entered)
if (col !== 2 || row < 2) return;
const symbol = sheet.getRange(row, 2).getValue();
if (!symbol) return;
// Fetch RSI and MACD at the time of entry
const rsi = CLAW_INDICATOR(symbol, "RSI_14", "H4");
const macd = CLAW_INDICATOR(symbol, "MACD", "H4");
// Write to RSI column (K) and MACD column (L)
sheet.getRange(row, 11).setValue(rsi);
sheet.getRange(row, 12).setValue(macd);
}
// Install the trigger
function createTrigger() {
ScriptApp.newTrigger("onTradeEntry")
.forSpreadsheet(SpreadsheetApp.getActive())
.onEdit()
.create();
} Live Watchlist with Auto-Refresh
/**
* Refresh all prices on the Live Prices tab.
* Set up a time-driven trigger to run every 5 minutes.
*/
function refreshWatchlist() {
const sheet = SpreadsheetApp.getActive().getSheetByName("Live Prices");
const symbols = sheet.getRange("A2:A20").getValues().flat().filter(Boolean);
for (let i = 0; i < symbols.length; i++) {
const row = i + 2;
const symbol = symbols[i];
try {
const price = CLAW_PRICE(symbol);
const rsi = CLAW_INDICATOR(symbol, "RSI_14", "H4");
const atr = CLAW_INDICATOR(symbol, "ATR_14", "H4");
sheet.getRange(row, 2).setValue(price); // Column B: Price
sheet.getRange(row, 3).setValue(rsi); // Column C: RSI
sheet.getRange(row, 4).setValue(atr); // Column D: ATR
sheet.getRange(row, 5).setValue(new Date()); // Column E: Last Update
} catch (err) {
sheet.getRange(row, 2).setValue("ERR");
}
}
}
// Set up auto-refresh every 5 minutes
function createRefreshTrigger() {
ScriptApp.newTrigger("refreshWatchlist")
.timeBased()
.everyMinutes(5)
.create();
} Performance Metrics Formulas
Use these formulas on the Dashboard tab to calculate key trading metrics:
Win Rate:
=COUNTIF(Trades!H2:H, ">"&0) / COUNTA(Trades!H2:H)
Average R-Multiple:
=AVERAGE(Trades!I2:I)
Profit Factor:
=SUMIF(Trades!H2:H, ">"&0) / ABS(SUMIF(Trades!H2:H, "<"&0))
Max Consecutive Losses:
(Use Apps Script for this -- too complex for a formula)
Expectancy:
=(Win Rate * Average Win) - ((1 - Win Rate) * Average Loss) Tips for Effective Journaling
Log the indicator state, not just the trade
Recording RSI, MACD, and ATR at entry lets you later analyze which indicator conditions produce your best trades.
Use R-multiples, not dollar amounts
A trade that made 2R is meaningful regardless of whether R was $50 or $500. R-multiples normalize your performance across varying position sizes.
Review weekly, not daily
Daily reviews encourage overtrading and emotional reactions. Weekly reviews give you enough data for pattern recognition.
Run this against live data.
Every account starts pay-as-you-go with $2.50 of credit and no card. Paste the key into the samples above and the requests work unchanged.