Building a NEPSE Screener with Moving Average Crossover Signals: A Python Implementation

Building a NEPSE Screener with Moving Average Crossover Signals: A Python Implementation

Many investors in the Nepalese stock market struggle to identify potential trading opportunities due to the lack of reliable and efficient stock screening tools. This post addresses this issue by providing a step-by-step guide on building a custom NEPSE stock screener using the moving average crossover strategy. As someone who has worked with financial data, I can attest to the importance of having a robust and accurate stock screener. In this post, we will walk through the process of creating a custom NEPSE stock screener that can help identify potential trading opportunities.

Key Takeaways

  • Learn how to retrieve historical stock prices of NEPSE-listed companies using the yfinance library.
  • Understand how to calculate moving averages and identify crossover signals using Python.
  • Discover how to create a custom stock screener that can help identify potential trading opportunities.

The Problem

The Nepalese stock market, like many others, is subject to fluctuations and uncertainties, making it challenging for investors to make informed decisions. A reliable and efficient stock screening tool can help investors identify potential trading opportunities and make more informed decisions. However, many existing stock screeners are either too complex or too simplistic, failing to provide the level of accuracy and reliability that investors need.

Data and Sources

The data source used in this post will be the historical stock prices of NEPSE-listed companies, which can be obtained from the Yahoo Finance website or the official NEPSE website. The yfinance library will be used to retrieve the historical stock prices. Data accessed on 2026-07-14.

Loading the Data

To load the historical stock prices, we will use the yfinance library. The following code snippet demonstrates how to retrieve the historical stock prices of a NEPSE-listed company.

import yfinance as yf
stock_data = yf.download('NEPSE', start='2020-01-01', end='2026-07-14')

Calculating Moving Averages

To calculate the moving averages, we will use the Pandas library. The following code snippet demonstrates how to calculate the 50-day and 200-day moving averages.

import pandas as pd
stock_data['MA_50'] = stock_data['Close'].rolling(window=50).mean()
stock_data['MA_200'] = stock_data['Close'].rolling(window=200).mean()

Identifying Crossover Signals

To identify the crossover signals, we will use the following logic: if the 50-day moving average crosses above the 200-day moving average, it's a buy signal; if the 50-day moving average crosses below the 200-day moving average, it's a sell signal. The following code snippet demonstrates how to identify the crossover signals.

stock_data['Signal'] = 0
stock_data.loc[(stock_data['MA_50'] > stock_data['MA_200']) & (stock_data['MA_50'].shift(1) <= stock_data['MA_200'].shift(1)), 'Signal'] = 1
stock_data.loc[(stock_data['MA_50'] < stock_data['MA_200']) & (stock_data['MA_50'].shift(1) >= stock_data['MA_200'].shift(1)), 'Signal'] = -1

Creating a Custom Stock Screener

To create a custom stock screener, we will use the following logic: if the stock has a buy signal and the current price is above the 200-day moving average, it's a potential buy opportunity; if the stock has a sell signal and the current price is below the 200-day moving average, it's a potential sell opportunity. The following code snippet demonstrates how to create a custom stock screener.

stock_data['Screen'] = 0
stock_data.loc[(stock_data['Signal'] == 1) & (stock_data['Close'] > stock_data['MA_200']), 'Screen'] = 1
stock_data.loc[(stock_data['Signal'] == -1) & (stock_data['Close'] < stock_data['MA_200']), 'Screen'] = -1

Complete Script

The full runnable script combining all steps:

import yfinance as yf
import pandas as pd

def load_data():
    stock_data = yf.download('NEPSE', start='2020-01-01', end='2026-07-14')
    return stock_data

def calculate_moving_averages(stock_data):
    stock_data['MA_50'] = stock_data['Close'].rolling(window=50).mean()
    stock_data['MA_200'] = stock_data['Close'].rolling(window=200).mean()
    return stock_data

def identify_crossover_signals(stock_data):
    stock_data['Signal'] = 0
    stock_data.loc[(stock_data['MA_50'] > stock_data['MA_200']) & (stock_data['MA_50'].shift(1) <= stock_data['MA_200'].shift(1)), 'Signal'] = 1
    stock_data.loc[(stock_data['MA_50'] < stock_data['MA_200']) & (stock_data['MA_50'].shift(1) >= stock_data['MA_200'].shift(1)), 'Signal'] = -1
    return stock_data

def create_custom_stock_screener(stock_data):
    stock_data['Screen'] = 0
    stock_data.loc[(stock_data['Signal'] == 1) & (stock_data['Close'] > stock_data['MA_200']), 'Screen'] = 1
    stock_data.loc[(stock_data['Signal'] == -1) & (stock_data['Close'] < stock_data['MA_200']), 'Screen'] = -1
    return stock_data

if __name__ == "__main__":
    stock_data = load_data()
    stock_data = calculate_moving_averages(stock_data)
    stock_data = identify_crossover_signals(stock_data)
    stock_data = create_custom_stock_screener(stock_data)
    print(stock_data)

Expected Output

The script will output the historical stock prices of the NEPSE-listed company, along with the 50-day and 200-day moving averages, the crossover signals, and the custom stock screener signals.

Limitations and Tradeoffs

This script has several limitations and tradeoffs. Firstly, it uses a simple moving average crossover strategy, which may not be effective in all market conditions. Secondly, it uses a fixed window size for the moving averages, which may not be optimal for all stocks. Finally, it does not take into account other technical and fundamental factors that may affect the stock price. In a production environment, a more sophisticated strategy and more robust parameters would be necessary.

Frequently Asked Questions

What is the moving average crossover strategy?

The moving average crossover strategy is a technical analysis strategy that involves using two moving averages with different window sizes to generate buy and sell signals.

How do I choose the window sizes for the moving averages?

The choice of window sizes for the moving averages depends on the specific stock and market conditions. A common approach is to use a short-term moving average (e.g. 50-day) and a long-term moving average (e.g. 200-day).

Can I use this script for other stocks?

Yes, you can use this script for other stocks by simply changing the stock symbol in the yfinance download function.

What I'd Change

In conclusion, while this script provides a basic framework for creating a custom stock screener, there are several areas that could be improved. Firstly, I would consider using a more sophisticated technical analysis strategy, such as the Relative Strength Index (RSI) or the Bollinger Bands. Secondly, I would consider incorporating fundamental factors, such as earnings per share or dividend yield, into the screener. Finally, I would consider using a more robust parameter optimization technique, such as grid search or genetic algorithms, to optimize the parameters of the moving averages and the screener. By making these changes, you could create a more effective and reliable stock screener that can help you make more informed investment decisions.

إرسال تعليق

Hi! How can we help you? Send us a message and we'll get back to you.