DEV Community

Danilo Jamaal
Danilo Jamaal

Posted on

Build a Dogecoin Sentiment-Driven Trading Signal CLI with Remix

Build a Dogecoin Sentiment-Driven Trading Signal CLI with Remix

⏱️ 20 min read | 📊 Beginner-Intermediate | 🛠️ Remix + LunarCrush API

Dogecoin, the meme-turned-crypto-phenomenon, is notorious for its volatile price swings often driven by social media buzz and online sentiment. Trying to trade Dogecoin based on gut feelings or lagging indicators can feel like navigating a minefield. Wouldn't it be powerful to have a tool that could sift through the noise and identify potential trading opportunities based on real-time sentiment analysis?

This tutorial will guide you through building a command-line interface (CLI) application that leverages LunarCrush's social intelligence data to generate Dogecoin trading signals. We're not just building a simple sentiment tracker; we're creating a tool that analyzes sentiment shifts and provides actionable buy/sell signals. Forget staring at charts all day; this CLI will do the heavy lifting for you, providing data-driven insights directly to your terminal.

Why is this valuable? Because in the world of crypto, information is power. Early detection of sentiment shifts can give you a significant edge, allowing you to capitalize on trends before they become mainstream. This tool benefits day traders looking for quick profits, swing traders aiming for longer-term gains, and even researchers interested in understanding the relationship between social sentiment and cryptocurrency prices. This isn't just about building a cool project; it's about creating a tool that can potentially improve your trading strategy and bottom line.

In this tutorial, we'll focus on identifying significant increases in positive sentiment as potential buy signals and significant increases in negative sentiment as potential sell signals. We'll be using the LunarCrush API to access real-time Dogecoin data, Remix to build the CLI, and some simple logic to interpret the data and generate the trading signals. Let's dive in and build something awesome!

Prerequisites

Before we get started, make sure you have the following:

  • Node.js 18+: You'll need Node.js to run the Remix application. You can download it from nodejs.org.
  • LunarCrush API key: You'll need a LunarCrush API key to access their data. You can get one for free (with limitations) or upgrade for higher rate limits and more features at lunarcrush.com/developers. Use code JAMAALBUILDS for 15% off.
  • Basic Remix knowledge: Familiarity with Remix concepts like routes, actions, and loaders will be helpful. If you're new to Remix, check out their official tutorial: https://remix.run/docs/en/main/tutorials/blog

Step 1: Setting Up the Remix Project

First, we need to create a new Remix project. Remix will handle the routing, data loading, and CLI execution for us.

Open your terminal and run the following commands:

npx create-remix@latest dogecoin-sentiment-cli
Enter fullscreen mode Exit fullscreen mode

When prompted, choose the following options:

  • Where do you want to create your app? dogecoin-sentiment-cli
  • What type of app do you want to create? Just the basics
  • TypeScript or JavaScript? TypeScript (or JavaScript, if you prefer)
  • Do you want to use Tailwind CSS? No
  • Do you want to use CSS Modules? No
  • Which data routing convention do you want to use? Remix Convention
  • Do you want to use future flags? No
  • Install dependencies with npm? Yes

This will create a new Remix project in a directory called dogecoin-sentiment-cli. Once the installation is complete, navigate into the project directory:

cd dogecoin-sentiment-cli
Enter fullscreen mode Exit fullscreen mode

Why are we using Remix? Remix provides a structured way to build web applications and CLIs. Its routing system allows us to easily define different commands for our CLI, and its data loading capabilities make it easy to fetch data from the LunarCrush API. Remix also handles the complexities of server-side rendering and data fetching, allowing us to focus on the core logic of our application. A common pitfall is trying to build a CLI from scratch without a framework. Remix simplifies the process significantly.

// app/routes/_.tsx
import type { ActionFunctionArgs } from "@remix-run/node";
import { json } from "@remix-run/node";

export async function action({ request }: ActionFunctionArgs) {
  const formData = await request.formData();
  const topic = formData.get("topic");

  if (!topic) {
    return json({ error: "Topic is required" }, { status: 400 });
  }

  try {
    const response = await fetch(
      `https://lunarcrush.com/api4/public/topic/v1?topic=${topic}`,
      {
        headers: {
          Authorization: `Bearer ${process.env.LUNARCRUSH_API_KEY}`,
        },
      }
    );

    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }

    const data = await response.json();
    return json({ data });
  } catch (error) {
    console.error("Error fetching data:", error);
    return json({ error: "Failed to fetch data" }, { status: 500 });
  }
}

export default function Index() {
  return (
    <div>
      <h1>Dogecoin Sentiment CLI</h1>
      <p>This is a basic Remix app.</p>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

After running these commands and examining the generated files, you should see a basic Remix project structure. You can start the development server by running npm run dev. However, we will be modifying the project to create a CLI, so the browser output is not relevant at this stage. If you encounter any errors during the installation process, double-check that you have Node.js 18+ installed and that your npm version is up-to-date.

Step 2: Configure Environment Variables

We need to store our LunarCrush API key securely. We'll use environment variables for this.

Create a .env file in the root of your project:

touch .env
Enter fullscreen mode Exit fullscreen mode

Add your LunarCrush API key to the .env file:

LUNARCRUSH_API_KEY=YOUR_LUNARCRUSH_API_KEY
Enter fullscreen mode Exit fullscreen mode

Important: Replace YOUR_LUNARCRUSH_API_KEY with your actual API key.

Next, install the dotenv package to load environment variables in your Remix app:

npm install dotenv
Enter fullscreen mode Exit fullscreen mode

Modify your remix.config.js file to include the dotenv configuration:

/** @type {import('@remix-run/dev').AppConfig} */
module.exports = {
  ignoredRouteFiles: ["**/.*", "**/*.css", "**/*.test.{js,jsx,ts,tsx}"],
  // add this:
  serverModuleFormat: "cjs",
  serverDependenciesToBundle: ['dotenv'],
  // ...
};
Enter fullscreen mode Exit fullscreen mode

Then, in your root route file (e.g., app/root.tsx or app/root.jsx), import and configure dotenv:

// app/root.tsx
import { useState, useEffect } from "react";

if (process.env.NODE_ENV === 'development') {
  require('dotenv').config();
}

// ... rest of your root component
Enter fullscreen mode Exit fullscreen mode

Why use environment variables? Storing API keys directly in your code is a major security risk. Environment variables allow you to keep sensitive information separate from your codebase, making it easier to manage and protect your credentials. It's a best practice to always use environment variables for API keys and other sensitive data. A common mistake is accidentally committing the .env file to your Git repository. Make sure to add .env to your .gitignore file to prevent this.

After these changes, your Remix application will be able to access the LunarCrush API key stored in the .env file. You can verify this by running console.log(process.env.LUNARCRUSH_API_KEY) in one of your route files. If the API key is printed to the console, you've successfully configured environment variables. If you encounter any issues, double-check that you've installed the dotenv package and that the .env file is in the correct location.

Step 3: Fetching Dogecoin Data from LunarCrush

Now, let's fetch the Dogecoin data from the LunarCrush API. We'll create a function to handle the API request.

Modify your app/routes/_.tsx file (or the relevant route file) to include the following code:

// app/routes/_.tsx
import type { ActionFunctionArgs } from "@remix-run/node";
import { json } from "@remix-run/node";

export async function action({ request }: ActionFunctionArgs) {
  const formData = await request.formData();
  const topic = formData.get("topic");

  if (!topic) {
    return json({ error: "Topic is required" }, { status: 400 });
  }

  try {
    const response = await fetch(
      `https://lunarcrush.com/api4/public/topic/v1?topic=${topic}`,
      {
        headers: {
          Authorization: `Bearer ${process.env.LUNARCRUSH_API_KEY}`,
        },
      }
    );

    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }

    const data = await response.json();
    return json({ data });
  } catch (error) {
    console.error("Error fetching data:", error);
    return json({ error: "Failed to fetch data" }, { status: 500 });
  }
}

export default function Index() {
  return (
    <div>
      <h1>Dogecoin Sentiment CLI</h1>
      <p>This is a basic Remix app.</p>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

This code defines an action function that fetches data from the LunarCrush API based on the provided topic. It handles errors and returns the data as JSON.

Why are we using the topic endpoint? The LunarCrush topic endpoint allows us to retrieve comprehensive data for a specific cryptocurrency, including its Galaxy Score™, Alt Rank™, sentiment, social mentions, price, and more. This data is essential for our sentiment analysis and trading signal generation. A common mistake is using the wrong API endpoint or passing incorrect parameters. Double-check the LunarCrush API documentation to ensure you're using the correct endpoint and parameters.

After adding this code, you should be able to fetch Dogecoin data from the LunarCrush API. You can test this by submitting a form with the topic set to "dogecoin". The API response will be logged to the console. If you encounter any errors, double-check that your API key is correct and that you're using the correct API endpoint. Also, be mindful of the API rate limits.

Step 4: Implementing Sentiment Analysis and Trading Signal Logic

Now for the core of our CLI: analyzing the sentiment data and generating trading signals. We'll add a function to interpret the LunarCrush data and determine whether to generate a buy or sell signal.

Modify your app/routes/_.tsx file to include the following code (modifying the action function):

// app/routes/_.tsx
import type { ActionFunctionArgs } from "@remix-run/node";
import { json } from "@remix-run/node";

interface LunarCrushResponse {
  data: {
    galaxy_score: string;
    alt_rank: string;
    sentiment: string;
    social_mentions_24h: string;
    social_contributors: string;
    price: string;
    price_change_24h: string;
    market_cap: string;
    volume_24h: string;
  }[];
}

function analyzeSentiment(data: LunarCrushResponse["data"]) {
  if (!data || data.length === 0) {
    return "No data available";
  }

  const dogecoinData = data[0];

  const sentimentScore = parseFloat(dogecoinData.sentiment);
  const priceChange24h = parseFloat(dogecoinData.price_change_24h);

  if (sentimentScore > 75 && priceChange24h > 0) {
    return "Strong BUY signal: High positive sentiment and price increase";
  } else if (sentimentScore > 60 && priceChange24h > 0) {
    return "BUY signal: Positive sentiment and price increase";
  } else if (sentimentScore < 25 && priceChange24h < 0) {
    return "Strong SELL signal: High negative sentiment and price decrease";
  } else if (sentimentScore < 40 && priceChange24h < 0) {
    return "SELL signal: Negative sentiment and price decrease";
  } else {
    return "NEUTRAL signal: Sentiment and price are not indicating a clear trend";
  }
}


export async function action({ request }: ActionFunctionArgs) {
  const formData = await request.formData();
  const topic = formData.get("topic");

  if (!topic) {
    return json({ error: "Topic is required" }, { status: 400 });
  }

  try {
    const response = await fetch(
      `https://lunarcrush.com/api4/public/topic/v1?topic=${topic}`,
      {
        headers: {
          Authorization: `Bearer ${process.env.LUNARCRUSH_API_KEY}`,
        },
      }
    );

    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }

    const jsonResponse = await response.json() as LunarCrushResponse;
    const tradingSignal = analyzeSentiment(jsonResponse.data);

    return json({ tradingSignal });
  } catch (error) {
    console.error("Error fetching data:", error);
    return json({ error: "Failed to fetch data" }, { status: 500 });
  }
}

export default function Index() {
  return (
    <div>
      <h1>Dogecoin Sentiment CLI</h1>
      <p>This is a basic Remix app.</p>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

This code adds an analyzeSentiment function that takes the LunarCrush data as input and returns a trading signal based on the sentiment score and price change. The function uses thresholds to determine whether the sentiment is positive, negative, or neutral, and generates a corresponding buy, sell, or neutral signal.

Why are we using sentiment and price change? Combining sentiment analysis with price change provides a more robust trading signal. Sentiment indicates the overall market feeling towards Dogecoin, while price change confirms whether that feeling is translating into actual market movement. This combination helps to filter out false signals and improve the accuracy of our trading decisions. A common pitfall is relying solely on sentiment without considering other factors like price action, volume, and market trends. Always use a combination of indicators for more reliable signals.

After adding this code, you should be able to generate trading signals based on the LunarCrush data. You can test this by submitting a form with the topic set to "dogecoin". The API response will include a tradingSignal field with the generated signal. If you encounter any errors, double-check that your sentiment analysis logic is correct and that you're handling the data properly. Experiment with different thresholds to fine-tune the signal generation.

Step 5: Transforming Remix into a CLI

Now, let's transform our Remix app into a CLI. We'll modify the entry.server.tsx file to handle CLI requests.

Create a file named cli.ts in the root of your project:

touch cli.ts
Enter fullscreen mode Exit fullscreen mode

Add the following code to cli.ts:

#!/usr/bin/env node
import { installGlobals } from "@remix-run/node";
import { execSync } from 'child_process';

installGlobals();

async function runCLI() {
  const topic = process.argv[2] || "dogecoin";

  try {
    const remixCommand = `node server.bundle/index.js --data='topic=${topic}'`;
    const output = execSync(remixCommand).toString();

    try {
        const parsedOutput = JSON.parse(output);
        if (parsedOutput.tradingSignal) {
            console.log(parsedOutput.tradingSignal);
        } else if (parsedOutput.data) {
            console.log("Raw data: ", parsedOutput.data);
        }
         else {
            console.error("Unexpected output:", parsedOutput);
        }
    } catch (jsonError) {
        console.error("Error parsing JSON:", jsonError);
        console.error("Raw output:", output);
    }

  } catch (error: any) {
    console.error("Failed to execute Remix command:", error.message);
  }
}

runCLI();
Enter fullscreen mode Exit fullscreen mode

Modify your package.json file to add a bin entry:

{
  "name": "dogecoin-sentiment-cli",
  "private": true,
  "sideEffects": false,
  "scripts": {
    "build": "remix build",
    "dev": "remix dev",
    "start": "remix-serve build",
    "typecheck": "tsc"
  },
  "dependencies": {
    "@remix-run/node": "^2.3.0",
    "@remix-run/react": "^2.3.0",
    "@remix-run/serve": "^2.3.0",
    "isbot": "^3.6.8",
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@remix-run/dev": "^2.3.0",
    "@remix-run/eslint-config": "^2.3.0",
    "@types/react": "^18.2.20",
    "@types/react-dom": "^18.2.7",
    "dotenv": "^16.3.1",
    "eslint": "^8.47.0",
    "typescript": "^5.1.6"
  },
  "engines": {
    "node": ">=18.0.0"
  },
  "bin": {
    "dogecoin-sentiment": "cli.ts"
  }
}
Enter fullscreen mode Exit fullscreen mode

Run npm install to update your dependencies and then run npm link to make the CLI globally available.

Now you can run the CLI from your terminal:

dogecoin-sentiment
Enter fullscreen mode Exit fullscreen mode

or

dogecoin-sentiment solana
Enter fullscreen mode Exit fullscreen mode

This will execute the Remix app and print the trading signal to the console.

Why are we using child_process.execSync? We're using child_process.execSync because it allows us to execute Remix commands from our CLI script. This is necessary to trigger the Remix action and retrieve the trading signal. While execSync is synchronous and can block the event loop, it's suitable for our CLI use case where we want to wait for the command to complete before printing the result. A common pitfall is using asynchronous methods like child_process.exec without properly handling the asynchronous nature of the command execution. This can lead to incorrect or incomplete results.

After these changes, you should be able to run the CLI from your terminal and see the trading signal printed to the console. If you encounter any errors, double-check that you've added the bin entry to your package.json file and that you've run npm install and npm link. Also, make sure that the cli.ts file has execute permissions.

Step 6: Improving the CLI Output

Let's make the CLI output more user-friendly by adding some formatting and colors. We'll use the chalk package for this.

Install the chalk package:

npm install chalk
Enter fullscreen mode Exit fullscreen mode

Modify your cli.ts file to include the following code:

#!/usr/bin/env node
import { installGlobals } from "@remix-run/node";
import { execSync } from 'child_process';
import chalk from 'chalk';

installGlobals();

async function runCLI() {
  const topic = process.argv[2] || "dogecoin";

  try {
    const remixCommand = `node server.bundle/index.js --data='topic=${topic}'`;
    const output = execSync(remixCommand).toString();

    try {
        const parsedOutput = JSON.parse(output);
        if (parsedOutput.tradingSignal) {
            let signalColor = chalk.white;
            if (parsedOutput.tradingSignal.includes("BUY")) {
                signalColor = chalk.green;
            } else if (parsedOutput.tradingSignal.includes("SELL")) {
                signalColor = chalk.red;
            }

            console.log(signalColor.bold(parsedOutput.tradingSignal));

        } else if (parsedOutput.data) {
            console.log(chalk.yellow("Raw data: "), parsedOutput.data);
        }
         else {
            console.error(chalk.red("Unexpected output:"), parsedOutput);
        }
    } catch (jsonError) {
        console.error(chalk.red("Error parsing JSON:"), jsonError);
        console.error(chalk.yellow("Raw output:"), output);
    }

  } catch (error: any) {
    console.error(chalk.red("Failed to execute Remix command:"), error.message);
  }
}

runCLI();
Enter fullscreen mode Exit fullscreen mode

This code imports the chalk package and uses it to colorize the CLI output. Buy signals are displayed in green, sell signals are displayed in red, and neutral signals are displayed in white.

Why are we using chalk? The chalk package allows us to add color and formatting to our CLI output, making it more visually appealing and easier to understand. Color-coding the trading signals helps users quickly identify the recommended action. A common pitfall is overusing colors or using colors that are difficult to read. Choose a color scheme that is easy on the eyes and provides clear visual cues.

After these changes, you should see the CLI output with colorized trading signals. If you encounter any errors, double-check that you've installed the chalk package and that you're using it correctly in your code.

Testing It Out

Now that we've built our Dogecoin Sentiment-Driven Trading Signal CLI, let's test it out and see how it works.

  1. Run the CLI: Open your terminal and run the following command:

    dogecoin-sentiment
    
  2. Observe the Output: The CLI will fetch Dogecoin data from the LunarCrush API, analyze the sentiment, and print a trading signal to the console. The signal will be color-coded: green for buy, red for sell, and white for neutral.

    Example Output:

    BUY signal: Positive sentiment and price increase
    
  3. Test with Different Topics: You can also test the CLI with other cryptocurrencies by passing the topic as an argument:

    dogecoin-sentiment solana
    
  4. Verify the Logic: To ensure the CLI is working correctly, you can manually verify the trading signals by comparing them to the actual Dogecoin sentiment and price data on LunarCrush.

  5. Test Edge Cases: Try running the CLI when the LunarCrush API is unavailable or when there is no data for Dogecoin. The CLI should handle these edge cases gracefully and provide informative error messages.

If everything is working correctly, you should see a color-coded trading signal based on the current Dogecoin sentiment and price data. If you encounter any issues, double-check your code, API key, and environment variables.

ROI & Monetization

Now that we've built our Dogecoin Sentiment-Driven Trading Signal CLI, let's explore how we can monetize it.

  1. Premium Trading Signals: Offer a premium version of the CLI with more advanced sentiment analysis, real-time data updates, and personalized trading signals. Charge a monthly subscription fee for access to these premium features.
*   **Example:** 50 users × $10/month = $500 MRR
Enter fullscreen mode Exit fullscreen mode
  1. Trading Bot Integration: Integrate the CLI with a trading bot to automate Dogecoin trades based on the generated trading signals. Charge a commission on each successful trade or a monthly fee for access to the trading bot integration.
*   **Example:** 1% commission on $10,000 monthly trading volume = $100/month per user.  10 users = $1000 MRR
Enter fullscreen mode Exit fullscreen mode
  1. API Access: Provide API access to the CLI's sentiment analysis and trading signal generation capabilities. Charge developers a fee for accessing the API.
*   **Example:** 5 developers × $20/month = $100 MRR
Enter fullscreen mode Exit fullscreen mode
  1. Alerting Service: Set up an alerting service that sends notifications to users when a strong buy or sell signal is generated. Charge a monthly fee for access to the alerting service.
*   **Example:** 25 users × $5/month = $125 MRR
Enter fullscreen mode Exit fullscreen mode
  1. SaaS Platform: Develop a SaaS platform that provides a comprehensive suite of cryptocurrency sentiment analysis tools, including the Dogecoin Sentiment-Driven Trading Signal CLI. Charge a monthly subscription fee for access to the platform.
*   **Example:** Basic tier at $15/month = 20 clients × $15 = $300 MRR. Enterprise tier at $200/month = 5 clients × $200 = $1000 MRR
Enter fullscreen mode Exit fullscreen mode

Break-even Analysis:

  • Development Costs: $500 (estimated time and resources)
  • Monthly Expenses: $100 (API usage, server costs)
  • Break-even Point: $600 / $10 (average revenue per user) = 60 users

You would need to acquire 60 paying users to break even on your initial investment.

Scaling Strategies:

  • Marketing: Promote your CLI and its features through social media, online forums, and cryptocurrency communities.
  • Partnerships: Partner with cryptocurrency exchanges, trading platforms, and financial news websites to reach a wider audience.
  • Content Marketing: Create valuable content, such as blog posts, tutorials, and webinars, to attract potential users and establish yourself as an expert in cryptocurrency sentiment analysis.

By implementing these monetization strategies and scaling strategies, you can turn your Dogecoin Sentiment-Driven Trading Signal CLI into a profitable business.

What's Next

Now that you have a working Dogecoin Sentiment-Driven Trading Signal CLI, here are some ideas for extending its functionality:

  1. Implement Technical Analysis: Integrate technical analysis indicators, such as moving averages and RSI, into the trading signal generation logic. This can help to improve the accuracy of the signals and provide a more comprehensive view of the market.
  2. Add Support for Multiple Cryptocurrencies: Extend the CLI to support multiple cryptocurrencies by allowing users to specify the cryptocurrency as a command-line argument. You can use the LunarCrush API to fetch data for a wide range of cryptocurrencies.
  3. Develop a Backtesting Feature: Create a backtesting feature that allows users to test the trading signal generation logic against historical data. This can help to evaluate the performance of the CLI and identify areas for improvement.
  4. Integrate with Trading Platforms: Integrate the CLI with popular trading platforms, such as Binance and Coinbase, to allow users to automate their trades based on the generated trading signals.
  5. Create a Dashboard: Build a web-based dashboard that provides a visual representation of the Dogecoin sentiment data and trading signals. This can make it easier for users to understand the data and make informed trading decisions.

To scale to multiple assets, you can modify the CLI to accept a list of cryptocurrency symbols as input. You can then iterate over the list and fetch data for each cryptocurrency from the LunarCrush API. You can also create a configuration file that allows users to specify their preferred cryptocurrencies and trading strategies.

The possibilities are endless! By combining the power of Remix, the LunarCrush API, and your creativity, you can build a truly valuable tool for cryptocurrency traders and investors.

Start building, experiment with different features, and see what you can create!

Top comments (0)