The crypto industry recently experienced an incredible bull market. Bitcoin has been holding steady at $100k for several days, and with policies from the Trump administration, the outlook for the coming months seems even more optimistic.
So, did I make money during this boom? Unfortunately, no. Despite having plenty of time on my hands, I found it overwhelming to keep up with the flood of information from Twitter and Telegram. While I attempted to consolidate information and pick a few promising assets, I lacked the confidence to hold them long-term without solid justification.
Most centralized exchanges (CEXs) provide auto-trading functionalities. However, in my personal experience, these features seem designed to split pooled USDT or KRW into small chunks, maximizing fees for the platform. While the AI behind these features is undoubtedly more mathematically adept than I am and does yield profits, it’s disheartening to see a 50% profit potential reduced to 40% or even 30%.
This is why I propose an auto-trading system based on various technical indicators, with decision-making delegated to ChatGPT. Such a system could strike a balance between optimizing profits and providing a transparent rationale for its actions.
The indicators I’ve selected for this project include:
Latest Google-Scraped News: While Twitter scraping is too costly, news headlines can still provide valuable sentiment insights.
Fear and Greed Index: A classic gauge of market sentiment.
OHLCV Indicators: Metrics like moving averages (MA), relative strength index (RSI), stochastic oscillator, MACD, and Bollinger Bands.
Candlestick Data: 30 days of daily candlesticks and 24 hours of minute-level candlesticks.
These indicators form the backbone of the trading logic, and I plan to create scripts that feed this data into GPT for decision-making. While there are likely better indicators out there, these provide a solid starting point.
For this sample application, I decided to use Bithumb’s open API, as it is a prominent exchange in South Korea. While I considered decentralized exchanges (DEXs), the high gas fees on recent blockchain networks discouraged me from pursuing that route. Moreover, for automated trading and selling scripts, the APIs provided by CEXs are much more straightforward to work with.
The primary Bithumb API endpoints I plan to use are:
[GET] /v1/accounts: To retrieve account information.
[GET] /v1/ticker: For real-time price data.
[POST] /v1/orders: To place buy or sell orders.
[GET] /v1/orderbook: To access market depth information.
One thing to note: the popular CEX interface npm package ccxt
has an outdated implementation for Bithumb. Since it is incompatible with the Bithumb API 2.0, I had to create a custom interface for connecting to the exchange.
Before using OpenAI’s chat.completion
feature, you need to set up billing. OpenAI’s API requires you to create a project, generate an API key, and make a minimum payment of $10 to activate API usage.
Additionally, for news scraping, I used the SERP API, which provides 100 free API calls during the first month after registration. This makes it the most cost-effective choice for scraping Google News headlines.
Stack: Node.js with TypeScript.
Infrastructure: AWS EC2 for background running, with PM2 for process management.
The key part of this system is getting mathematical indicatiors from orderbook. I attatch my code snippet for everyone.
Here’s a brief explanation of the key indicators used:
SMA 10 (Simple Moving Average): A simple average of the closing prices over the last 10 periods. It helps smooth out price action.
EMA 10 (Exponential Moving Average): Similar to SMA but gives more weight to recent prices, making it more responsive to new information.
RSI 14 (Relative Strength Index): A momentum oscillator that measures the speed and change of price movements over 14 periods. Values above 70 indicate overbought conditions, while values below 30 suggest oversold conditions.
Stochastic K and D: These indicators measure the closing price relative to a price range over a set period.
Stochastic K (%K): Reflects the current closing price as a percentage of the high-low range over a specific period.
Stochastic D (%D): A smoothed version of %K, usually a 3-period moving average of %K.
MACD (Moving Average Convergence Divergence): A trend-following momentum indicator that shows the relationship between two moving averages of a security’s price (typically 12-day EMA and 26-day EMA).
Bollinger Bands: A volatility indicator consisting of three lines:
Middle Band: The 20-period simple moving average (SMA) of closing prices.
Upper Band: Two standard deviations above the middle band.
Lower Band: Two standard deviations below the middle band.
import {
BollingerBands,
EMA,
MACD,
RSI,
SMA,
Stochastic,
} from "technicalindicators";
function addTradingIndicator(data: CEX.OHLCV[]) {
const closePrices = data.map((row) => row.close);
const highPrices = data.map((row) => row.high);
const lowPrices = data.map((row) => row.low);
// Moving Averages
const SMA_10 = SMA.calculate({ period: 10, values: closePrices });
const EMA_10 = EMA.calculate({ period: 10, values: closePrices });
// RSI
const RSI_14 = RSI.calculate({ period: 14, values: closePrices });
// Stochastic Oscillator
const stochastic = Stochastic.calculate({
high: highPrices,
low: lowPrices,
close: closePrices,
period: 14,
signalPeriod: 3,
});
// MACD
const macd = MACD.calculate({
values: closePrices,
fastPeriod: 12,
slowPeriod: 26,
signalPeriod: 9,
SimpleMAOscillator: false,
SimpleMASignal: false,
});
// Bollinger Bands
const bollingerBands = BollingerBands.calculate({
period: 20,
values: closePrices,
stdDev: 2,
});
return data.map((row, i) => ({
...row,
SMA_10: SMA_10[i] || null,
EMA_10: EMA_10[i] || null,
RSI_14: RSI_14[i] || null,
Stochastic_K: stochastic[i]?.k || null,
Stochastic_D: stochastic[i]?.d || null,
MACD: macd[i]?.MACD || null,
Signal_Line: macd[i]?.signal || null,
MACD_Histogram: macd[i]?.histogram || null,
Middle_Band: bollingerBands[i]?.middle || null,
Upper_Band: bollingerBands[i]?.upper || null,
Lower_Band: bollingerBands[i]?.lower || null,
}));
}
After implenmenting calculations for OHLCV-based metrics and upper indicators, we need to analyze with Open AI's API. I constructed prompts that provide GPT with structured data and request trading recommendations.
askToGPT({
recentNews,
technicalAnalysis,
lastDecisions,
fnbIndex,
myAccountStatus,
}: {
recentNews: string;
technicalAnalysis: string;
lastDecisions: string;
fnbIndex: string;
myAccountStatus: string;
}) {
const instructions = this.getInstructions();
if (!instructions) {
console.log("No instruction found");
return;
}
try {
const client = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
const response = await client.chat.completions.create({
model: "gpt-4o",
messages: [
{ role: "system", content: instructions },
{ role: "user", content: recentNews },
{ role: "user", content: technicalAnalysis },
{ role: "user", content: lastDecisions },
{ role: "user", content: fnbIndex },
{ role: "user", content: myAccountStatus },
],
response_format: { type: "json_object" },
});
return response.choices[0].message.content;
} catch (error) {
//...
}
}
Be aware of the response should be always structured json type. In my case, The response scripts are like this.
{
"decision": "hold" | "buy" | "sell",
"volume": number,
"reason": string,
}
With the trading logic finalized, I automated order placements via Bithumb's API.
async function buy(percentage: number) {
try {
const balances = await this.getBalance("sol");
const tradePrice = await this.getCurrentPrice("SOL");
if (!balances.krw.free || balances.krw.free <= 5000) {
throw new Error("Not enough KRW");
}
const volume = (
(balances.krw.free * (percentage / 100)) /
tradePrice
).toFixed(4);
const body = {
market: "KRW-SOL",
side: "bid",
volume: volume,
price: String(tradePrice),
ord_type: "limit",
};
const query = querystring.encode(body);
const hash = crypto.createHash("SHA512");
const queryHash = hash.update(query, "utf-8").digest("hex");
const payload = {
access_key: config.bithumb.apiKey,
nonce: uuidv4(),
timestamp: Date.now(),
query_hash: queryHash,
query_hash_alg: "SHA512",
};
const token = jwt.sign(payload, config.bithumb.secretKey);
const order = await bithumbClient.post("/v1/orders", body, {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
});
return order;
} catch (error) {
if (isAxiosError(error)) {
throw { code: error.status, message: error.message };
}
throw error;
}
}
async sell(percentage: number) {
try {
const balances = await this.getBalance("sol");
const tradePrice = await this.getCurrentPrice("SOL");
if (!balances.target.free) {
throw new Error("Not enough SOL");
}
const amount = balances.target.free * (percentage / 100);
if (tradePrice! * amount < 5000) {
throw new Error("Less than minimum order volume");
}
const body = {
market: "KRW-SOL",
side: "ask",
volume: String(amount),
price: String(tradePrice),
ord_type: "limit",
};
const query = new URLSearchParams(body).toString();
const hash = crypto.createHash("SHA512");
const queryHash = hash.update(query, "utf-8").digest("hex");
const payload = {
access_key: config.bithumb.apiKey,
nonce: uuidv4(),
timestamp: Date.now(),
query_hash: queryHash,
query_hash_alg: "SHA512",
};
const token = jwt.sign(payload, config.bithumb.secretKey);
console.log(body);
const order = await bithumbClient.post("/v1/orders", body, {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
});
return order;
} catch (error) {
if (isAxiosError(error)) {
throw { code: error.status, message: error.message };
}
throw error;
}
}
The auto-trading system demonstrates a promising approach for retail investors overwhelmed by information overload and skeptical of generic CEX auto-trade functionalities. By integrating technical indicators with GPT’s advanced reasoning capabilities, the system strikes a balance between sophistication and simplicity.
Improved Data Sources: Incorporating more granular sentiment analysis from platforms like Reddit or Twitter (if cost-effective).
Advanced Trading Logic: Exploring reinforcement learning models that adapt over time.
Multi-Exchange Support: Extending the system to operate across multiple exchanges for arbitrage opportunities.
Perptual Futures Trading Support: Exploring futures trading to achieve more effective profit potential.
The journey to building a robust auto-trading system is ongoing, but the foundation is set. This project highlights how modern AI tools can empower individuals to navigate complex markets with confidence.
Jio.Jake