Tutorial: Create indicator with Cursor IDE
This tutorial will guide you through the process of creating a new indicator using Cursor IDE.
Introduction
Cursor IDE is a fork of VS Code that has powerful AI capabilities, allowing it to access your code directly and have information about your project.
Cursor can also be provided with FTO custom indicator documentation to assist in creating new indicators.
Step 1: Install Cursor and set up the project
How to install Cursor and set up the project is described in this guide. If you don’t yet know how to set up your environment to work with the FTO API for indicators, that is also covered in the same guide.
Step 2: Apply Cursor Rules
The Rules feature in Cursor IDE allows users to define custom guidelines or behaviors that the AI should follow when generating code. By setting up rules that describe how indicators work in FTO, you can effectively teach Cursor the context it needs to produce accurate and consistent indicators.
To set up global rules for Cursor, click the setting icon (Picture #1)

From here, click the Rules setting (Picture #2)

In the User Rules field (Picture #3), download and paste contents of the file below called Rules.txt

Step 3: Upload FTO indicator documentation to Cursor
You can upload the FTO indicator documentation to Cursor, and Cursor will be able to use it to help you create new indicators.
To upload the FTO indicator documentation to Cursor, you need to follow these steps:
1. Click the setting icon in the top right corner of the Cursor IDE. (Picture #4)

2. Select "Features" on the left sidebar (Picture #5).

Scroll down until you see Docs (Picture #6)

Click on the "Add new doc" button and insert link https://fto-2.gitbook.io/fto-indicators-docs to the FTO indicator documentation (Picture #7).

After some indexing, Cursor will be able to refer to the documentation to help you create new indicators.
To become more familiar with how to use this added documentation in your requests to Cursor, go to the Recommendations section below.
Step 4: Getting familiar with Cursor
To open Cursors AI window, you can press Ctrl+L
or click on the icon in the top right corner of the Cursor IDE (Picture #8)

This panel has a chat interface and in Cursor version 0.47.8 it has 3 modes, Agent, Ask and Edit,
each catering to different needs during development (Picture #9).
Agent Mode: This mode allows for automated code generation and completion by interacting with the AI. It helps streamline the coding process by providing intelligent suggestions and solutions. I access your project files directly and suggests code which you can accept or reject
Ask Mode: In this mode, developers can ask questions about their codebase, programming concepts, or any development-related topics. The AI will respond with helpful guidance and explanations.
Edit Mode: Edit Mode assists in making modifications to the existing code. It aids in refactoring, simplifying, or improving code sections as needed.
What makes these modes powerful is the ability to add context directly from your project or documentation
For now, select the Ask mode

Next to the "select mode menu" there is also an option to select a model of AI that we want to use, for now we should choose Auto-select (Picture#10).

Step 5: Start building
Before we begin writing the indicator, it is expected that you are familiar with how to set up the environment to access the FTO Indicator API. If not, please read this guide first before continuing.
For this example, we will ask Cursor to implement the On Balance Volume (OBV) indicator for us. In this guide, we will start with an empty file, but for future indicator implementations, you can use some of our indicator foundations provided in this section.
In the request to create the OBV indicator for us, I included the FTO documentation for context and added the Rules discussed earlier. In the screenshot, you can see the sections of the documentation it decided to use (Picture #11).

In the result, we got code below
import { IndicatorImplementation, TDrawStyle, TPenStyle, TOutputWindow, TIndexBuffer } from "forex-tester-custom-indicator-api";
export default class OBVIndicator extends IndicatorImplementation {
// Declare the buffer as a class property
public obvBuffer!: TIndexBuffer;
Init(): void {
this.api.RecalculateMeAlways();
// Set indicator name
this.api.IndicatorShortName("On Balance Volume (OBV)");
// Configure to display in separate window since OBV is an oscillator
this.api.SetOutputWindow(TOutputWindow.SEPARATE_WINDOW);
// Register the number of buffers we'll use
this.api.IndicatorBuffers(1);
// Create and initialize the OBV buffer
this.obvBuffer = this.api.CreateIndexBuffer();
// Bind buffer to index 0
this.api.SetIndexBuffer(0, this.obvBuffer);
// Configure buffer appearance
this.api.SetIndexStyle(0, TDrawStyle.LINE, TPenStyle.SOLID, 1, "#0000FF"); // Blue line
this.api.SetIndexLabel(0, "OBV");
}
Calculate(index: number): void {
// If this is the first bar (rightmost/newest), initialize OBV
if (index === this.api.Bars() - 1) {
this.obvBuffer.setValue(index, this.api.Volume(index));
return;
}
// Get current and previous close prices
const currentClose = this.api.Close(index);
const previousClose = this.api.Close(index + 1);
// Get current volume
const volume = this.api.Volume(index);
// Get previous OBV value
const previousOBV = this.obvBuffer.getValue(index + 1);
let currentOBV;
// Calculate OBV based on price movement
if (currentClose > previousClose) {
// If price increased, add volume
currentOBV = previousOBV + volume;
} else if (currentClose < previousClose) {
// If price decreased, subtract volume
currentOBV = previousOBV - volume;
} else {
// If price unchanged, OBV remains the same
currentOBV = previousOBV;
}
// Set the calculated OBV value
this.obvBuffer.setValue(index, currentOBV);
}
}
The current logic seems correct, but it's using only the Close price, and there is currently no way for the user to specify their own price type. Let's ask it to fix that (Picture #12).

The code that Cursor wrote in his second response is below
import {
IndicatorImplementation,
TDrawStyle,
TPenStyle,
TOutputWindow,
TIndexBuffer,
TOptionType,
TOptValue_number
} from "forex-tester-custom-indicator-api";
export default class OBVIndicator extends IndicatorImplementation {
// Declare the buffer as a class property
public obvBuffer!: TIndexBuffer;
// Declare price type parameter
public priceType!: TOptValue_number;
Init(): void {
this.api.RecalculateMeAlways();
// Set indicator name
this.api.IndicatorShortName("On Balance Volume (OBV)");
// Configure to display in separate window since OBV is an oscillator
this.api.SetOutputWindow(TOutputWindow.SEPARATE_WINDOW);
// Initialize price type parameter
this.priceType = this.api.createTOptValue_number(0); // Default to Close price
// Register price type parameter as an enum
this.api.RegOption(
"Price Type",
TOptionType.ENUM_TYPE,
this.priceType
);
// Add price type options
this.api.AddOptionValue("Price Type", "Close");
this.api.AddOptionValue("Price Type", "Open");
this.api.AddOptionValue("Price Type", "High");
this.api.AddOptionValue("Price Type", "Low");
this.api.AddOptionValue("Price Type", "Median ((H+L)/2)");
this.api.AddOptionValue("Price Type", "Typical ((H+L+C)/3)");
// Register the number of buffers we'll use
this.api.IndicatorBuffers(1);
// Create and initialize the OBV buffer
this.obvBuffer = this.api.CreateIndexBuffer();
// Bind buffer to index 0
this.api.SetIndexBuffer(0, this.obvBuffer);
// Configure buffer appearance
this.api.SetIndexStyle(0, TDrawStyle.LINE, TPenStyle.SOLID, 1, "#0000FF"); // Blue line
this.api.SetIndexLabel(0, "OBV");
}
private getPrice(index: number): number {
switch (this.priceType.value) {
case 0: // Close
return this.api.Close(index);
case 1: // Open
return this.api.Open(index);
case 2: // High
return this.api.High(index);
case 3: // Low
return this.api.Low(index);
case 4: // Median
return (this.api.High(index) + this.api.Low(index)) / 2;
case 5: // Typical
return (this.api.High(index) + this.api.Low(index) + this.api.Close(index)) / 3;
default:
return this.api.Close(index); // Fallback to Close
}
}
Calculate(index: number): void {
// If this is the first bar (rightmost/newest), initialize OBV
if (index === this.api.Bars() - 1) {
this.obvBuffer.setValue(index, this.api.Volume(index));
return;
}
// Get current and previous prices using selected price type
const currentPrice = this.getPrice(index);
const previousPrice = this.getPrice(index + 1);
// Get current volume
const volume = this.api.Volume(index);
// Get previous OBV value
const previousOBV = this.obvBuffer.getValue(index + 1);
let currentOBV;
// Calculate OBV based on price movement
if (currentPrice > previousPrice) {
// If price increased, add volume
currentOBV = previousOBV + volume;
} else if (currentPrice < previousPrice) {
// If price decreased, subtract volume
currentOBV = previousOBV - volume;
} else {
// If price unchanged, OBV remains the same
currentOBV = previousOBV;
}
// Set the calculated OBV value
this.obvBuffer.setValue(index, currentOBV);
}
}
And with the addition of this new parameter and internal method, we get a nice dropdown with price types (Picture #13).

So in the end, we got a proper indicator with just two simple requests by setting up Cursor properly and providing it with Rules and documentation for context.
Recommendations
For Cursor to use the documentation that we provided in Step 3 we need to do the following:
Start by selecting the Ask mode and add context to your query by typing @ and selecting Docs from the drop-down menu (Picture #14).

In the drop-down menu, select FTO Indicator documentation, which we added earlier in Step 3 (Picture#15)

And provide add a file in which you want to create the indicator, you can do it by drag and dropping it from explorer window on the left onto the chat window or finding it in the @ drop-down menu under Files & folders (Picture #16)

Last updated