Skip to content

Field Conditions

Building and using field conditions in queries.

Overview

Field conditions represent comparisons that can be used in where() clauses. They are created by calling comparison methods on fields.

Creating Conditions

Basic Comparisons

typescript
import { StockField } from 'tradingview-screener';

// Create conditions using field methods
const priceAbove100 = StockField.PRICE.gt(100);
const volumeHigh = StockField.VOLUME.gte(1_000_000);
const marketCapLarge = StockField.MARKET_CAPITALIZATION.between(1e9, 100e9);

Condition Structure

A FieldCondition contains:

  • field - The field being compared
  • operation - The comparison operation (gt, lt, between, etc.)
  • value - The value(s) to compare against
typescript
const condition = StockField.PRICE.gt(100);

console.log(condition.field);      // StockField.PRICE
console.log(condition.operation);  // "greater"
console.log(condition.value);      // 100

Using Conditions

In where() Clauses

typescript
const screener = new StockScreener();

// Create condition
const condition = StockField.PRICE.gt(100);

// Use in where clause
screener.where(condition);

Inline Creation

Most commonly, conditions are created inline:

typescript
screener
  .where(StockField.PRICE.gt(100))
  .where(StockField.VOLUME.gte(1_000_000))
  .where(StockField.MARKET_CAPITALIZATION.between(1e9, 100e9));

Comparison Methods

Numeric Comparisons

typescript
// Greater than
StockField.PRICE.gt(100)

// Greater than or equal
StockField.PRICE.gte(100)

// Less than
StockField.PRICE.lt(500)

// Less than or equal
StockField.PRICE.lte(500)

// Equal
StockField.NAME.eq('Apple Inc.')

// Not equal
StockField.NAME.ne('Tesla Inc.')

Range Comparisons

typescript
// Between (inclusive)
StockField.MARKET_CAPITALIZATION.between(1e9, 100e9)

// Not between
StockField.RSI.notBetween(30, 70)  // Overbought or oversold

List Comparisons

typescript
// In list - using string field
StockField.NAME.isin(['Apple Inc.', 'Microsoft Corporation', 'Amazon.com Inc.'])

// Not in list - using description field
StockField.DESCRIPTION.notIn(['penny stock', 'OTC traded'])

Text Comparisons

typescript
// Match pattern (regex)
StockField.NAME.match('.*bank.*')

// Not match pattern
StockField.DESCRIPTION.notMatch('.*acquisition.*')

Condition Validation

Field-to-Field Comparison Prevention

Conditions validate that you're not comparing fields directly:

typescript
// ✗ This throws an error
try {
  StockField.PRICE.gt(StockField.VOLUME);
} catch (error) {
  console.error('Field-to-field comparisons not supported');
}

// ✓ Compare to a constant value
StockField.PRICE.gt(100);

Type Safety

TypeScript ensures type-safe comparisons:

typescript
// ✓ Valid
StockField.PRICE.gt(100);           // number to number
StockField.NAME.eq('Apple Inc.');   // string to string

// ✗ Type errors
StockField.PRICE.gt('expensive');   // Error: string not assignable to number
StockField.NAME.gt(5);              // Error: number not valid for text field

Converting Conditions to Filters

Conditions are converted to internal Filter objects:

typescript
const condition = StockField.PRICE.gt(100);

// Convert to filter (done automatically by where())
const filter = condition.toFilter();

console.log(filter.left);       // "close" (field name)
console.log(filter.operation);  // "greater"
console.log(filter.right);      // 100

Reusing Conditions

Conditions can be stored and reused:

typescript
// Define reusable conditions
const largeCap = StockField.MARKET_CAPITALIZATION.gt(10e9);
const highVolume = StockField.VOLUME.gte(1_000_000);
const profitable = StockField.NET_INCOME_TTM.gt(0);

// Use in multiple queries
const screener1 = new StockScreener()
  .where(largeCap)
  .where(highVolume);

const screener2 = new StockScreener()
  .where(largeCap)
  .where(profitable);

Condition Patterns

Value Range Pattern

typescript
// Define acceptable range
const priceInRange = StockField.PRICE.between(10, 500);
const peRatioInRange = StockField.PRICE_TO_EARNINGS_RATIO_TTM.between(10, 20);

screener
  .where(priceInRange)
  .where(peRatioInRange);

Threshold Pattern

typescript
// Define minimum thresholds
const minimumMarketCap = StockField.MARKET_CAPITALIZATION.gt(1e9);
const minimumVolume = StockField.VOLUME.gte(500_000);
const minimumDividend = StockField.DIVIDEND_YIELD_FWD.gte(2);

screener
  .where(minimumMarketCap)
  .where(minimumVolume)
  .where(minimumDividend);

Exclusion Pattern

typescript
// Define exclusion criteria
const notPennyStock = StockField.PRICE.gt(5);
const lowVolatility = StockField.ATR.lt(2);
const highPE = StockField.PRICE_TO_EARNINGS_RATIO_TTM.lt(50);

screener
  .where(notPennyStock)
  .where(lowVolatility)
  .where(highPE);

Sector Inclusion Pattern

typescript
// Define company name whitelist
const preferredCompanies = StockField.NAME.isin([
  'Apple Inc.',
  'Microsoft Corporation',
  'Amazon.com Inc.'
]);

screener.where(preferredCompanies);

Combining Conditions

Multiple Conditions (AND)

All conditions are ANDed together:

typescript
screener
  .where(StockField.PRICE.gt(10))           // AND
  .where(StockField.PRICE.lt(500))          // AND
  .where(StockField.VOLUME.gte(100_000));   // AND

Simulating OR with isin()

typescript
// Company is Apple OR Microsoft (using isin)
screener.where(StockField.NAME.isin(['Apple Inc.', 'Microsoft Corporation']));

// Equivalent to:
// WHERE name = 'Apple Inc.' OR name = 'Microsoft Corporation'

Debugging Conditions

typescript
const condition = StockField.PRICE.gt(100);

console.log(condition.toString());
// Output: "PRICE greater 100"

console.log(`Field: ${condition.field.name}`);
console.log(`Operation: ${condition.operation}`);
console.log(`Value: ${condition.value}`);

Debug Screener with Conditions

typescript
const screener = new StockScreener();

screener
  .where(StockField.PRICE.gt(100))
  .where(StockField.VOLUME.gte(1_000_000));

// Print the query
const results = await screener.get(true);  // Pass true to print request

TypeScript Type Inference

Conditions are fully typed:

typescript
import { FieldCondition } from 'tradingview-screener';

// Type is inferred
const condition: FieldCondition = StockField.PRICE.gt(100);

// Access properties with autocomplete
condition.field.  // <-- IDE shows field properties
condition.operation  // <-- Type: string
condition.value     // <-- Type: number

Best Practices

1. Create Conditions Close to Usage

typescript
// Good: Inline conditions
screener
  .where(StockField.PRICE.gt(100))
  .where(StockField.VOLUME.gte(1_000_000));

// Also good: Named conditions when reused
const largeCap = StockField.MARKET_CAPITALIZATION.gt(10e9);
screener1.where(largeCap);
screener2.where(largeCap);

2. Use Descriptive Names for Stored Conditions

typescript
// Good: Clear names
const isProfitable = StockField.NET_INCOME_TTM.gt(0);
const hasHighDividend = StockField.DIVIDEND_YIELD_FWD.gt(3);
const isLargeCap = StockField.MARKET_CAPITALIZATION.gt(10e9);

// Avoid: Unclear names
const condition1 = StockField.NET_INCOME_TTM.gt(0);
const c2 = StockField.DIVIDEND_YIELD_FWD.gt(3);

3. Validate Inputs

typescript
// Good: Validate before creating condition
function createPriceFilter(minPrice: number) {
  if (minPrice <= 0) {
    throw new Error('Price must be positive');
  }
  return StockField.PRICE.gte(minPrice);
}

// Use validated condition
const priceCondition = createPriceFilter(100);
screener.where(priceCondition);
typescript
// Good: Group by category
// Valuation conditions
const lowPE = StockField.PRICE_TO_EARNINGS_RATIO_TTM.lt(15);
const lowPB = StockField.PRICE_TO_BOOK_MRQ.lt(3);

// Quality conditions
const profitable = StockField.NET_INCOME_TTM.gt(0);
const growingRevenue = StockField.REVENUE_TTM_YOY_GROWTH.gt(10);

screener
  .where(lowPE)
  .where(lowPB)
  .where(profitable)
  .where(growingRevenue);

Common Pitfalls

Comparing Fields Directly

typescript
// ✗ Don't do this
StockField.PRICE.gt(StockField.VOLUME);  // Error!

// ✓ Compare to constant values
StockField.PRICE.gt(100);

Wrong Operator Types

typescript
// ✗ Using numeric operator on text field
StockField.NAME.gt('A');  // Doesn't make sense

// ✓ Use appropriate operators
StockField.NAME.match('.*bank.*');  // Text pattern
StockField.PRICE.gt(100);           // Numeric comparison

Next Steps

Released under the MIT License.