[Go to site: main page, start]

0% found this document useful (0 votes)
5 views36 pages

NEPSE Stock Prediction Dashboard Code

The document contains Java code for a stock portfolio management system using Spring framework, including controllers for dashboard, portfolio, and predictions. It defines entities for Portfolio, StockData, and User, along with data transfer objects (DTOs) for handling requests and responses. The system allows users to view their portfolio, add or remove stocks, and predict stock prices using LSTM models.

Uploaded by

Shiva Acharya
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views36 pages

NEPSE Stock Prediction Dashboard Code

The document contains Java code for a stock portfolio management system using Spring framework, including controllers for dashboard, portfolio, and predictions. It defines entities for Portfolio, StockData, and User, along with data transfer objects (DTOs) for handling requests and responses. The system allows users to view their portfolio, add or remove stocks, and predict stock prices using LSTM models.

Uploaded by

Shiva Acharya
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

1.

Controller
package [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

@Controller
@RequestMapping("/dashboard")
public class DashboardController {

private final LstmPredictionService predictionService;


private final PortfolioService portfolioService;
private final StockDataService stockDataService;

public DashboardController(LstmPredictionService predictionService,


PortfolioService portfolioService,
StockDataService stockDataService) {
[Link] = predictionService;
[Link] = portfolioService;
[Link] = stockDataService;
}

@GetMapping
public String showDashboard(Model model) {
Long userId = 1L; // Example user ID

try {
[Link]("NABIL", 60);
PredictionResult prediction = [Link]("NABIL");
[Link]("prediction", prediction);
} catch (Exception e) {
[Link]("predictionError", "Error predicting stock: " + [Link]());
}

PortfolioSummary portfolio = [Link](userId);


[Link]("portfolio", portfolio);
[Link]("topGainers", [Link](5));
[Link]("topLosers", [Link](5));

return "dashboard";
}

@PostMapping("/predict")
public String predictStock(@RequestParam String symbol,
Model model) {
Long userId = 1L; // Example user ID

try {
PredictionResult prediction = [Link](symbol);
[Link]("prediction", prediction);
} catch (Exception e) {
[Link]("predictionError", "Error predicting stock: " + [Link]());
}

PortfolioSummary portfolio = [Link](userId);


[Link]("portfolio", portfolio);
[Link]("topGainers", [Link](5));
[Link]("topLosers", [Link](5));

return "dashboard";
}
}
package [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

@Controller
@RequestMapping("/portfolio")
public class PortfolioController {

private final PortfolioService portfolioService;


public PortfolioController(PortfolioService portfolioService) {
[Link] = portfolioService;
}

@GetMapping
public String showPortfolio(Model model) {
// Hardcode user ID or use session-based approach
Long userId = 1L; // Example user ID
PortfolioSummary portfolio = [Link](userId);

[Link]("portfolio", portfolio);
[Link]("portfolioRequest", new PortfolioRequest());
return "portfolio";
}

@PostMapping("/add")
public String addToPortfolio(@ModelAttribute PortfolioRequest request,
Model model) {
Long userId = 1L; // Example user ID

try {
[Link](
userId,
[Link](),
[Link](),
[Link]()
);
[Link]("success", "Stock added to portfolio successfully");
} catch (Exception e) {
[Link]("error", "Failed to add stock: " + [Link]());
}

return "redirect:/portfolio";
}

@PostMapping("/remove")
public String removeFromPortfolio(@ModelAttribute PortfolioRequest request,
Model model) {
Long userId = 1L; // Example user ID

try {
[Link](
userId,
[Link](),
[Link]()
);
[Link]("success", "Stock removed from portfolio successfully");
} catch (Exception e) {
[Link]("error", "Failed to remove stock: " + [Link]());
}

return "redirect:/portfolio";
}
}

package [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

@Controller
@RequestMapping("/prediction")
public class PredictionController {

private final LstmPredictionService predictionService;

public PredictionController(LstmPredictionService predictionService) {


[Link] = predictionService;
}

@GetMapping
public String showPrediction(@RequestParam(required = false) String symbol,
Model model) {
String predictionSymbol = symbol != null ? symbol : "NEPSE";

try {
PredictionResult prediction = [Link](predictionSymbol);
[Link]("prediction", prediction);
[Link]("symbol", predictionSymbol);
} catch (Exception e) {
[Link]("error", "Error generating prediction: " + [Link]());
}
// Remove user reference
return "prediction";
}
}
[Link]
package [Link];

import [Link].*;
import [Link];
import [Link];
import [Link];

import [Link];

@Entity
@Table(name = "portfolio")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Portfolio {

@Id
@GeneratedValue(strategy = [Link])
private Long id;

@ManyToOne(fetch = [Link])
@JoinColumn(name = "user_id", nullable = false)
private User user;

@Column(nullable = false)
private String symbol;

@Column(nullable = false)
private int quantity;

@Column(nullable = false)
private double averagePrice;

@Column(nullable = false)
private LocalDate purchaseDate = [Link]();

@Column(nullable = false)
private String transactionType; // BUY or SELL
private String notes;

@Column(nullable = false)
private double totalInvestment;

// Additional fields for tracking


private double currentValue;
private double profitLoss;
private double profitLossPercentage;
}
package [Link];

import [Link].*;
import [Link];
import [Link];
import [Link];

import [Link];

@Entity
@Table(name = "stock_data")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class StockData {

@Id
@GeneratedValue(strategy = [Link])
private Long id;

@Column(nullable = false)
private String symbol;

@Column(nullable = false)
private LocalDate date;

@Column(nullable = false)
private double openingPrice;

@Column(nullable = false)
private double closingPrice;

@Column(nullable = false)
private double highPrice;

@Column(nullable = false)
private double lowPrice;

@Column(nullable = false)
private long volume;

@Column(nullable = false)
private double changeAmount;

@Column(nullable = false)
private double changePercentage;

// Additional technical indicators for LSTM model


private double movingAverage5;
private double movingAverage20;
private double movingAverage50;
private double rsi14;
private double macd;
private double bollingerUpper;
private double bollingerLower;
}
package [Link];

import [Link].*;
import [Link];
import [Link];
import [Link];
import [Link];

@Entity
@Table(name = "users")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = [Link])
private Long id;

@Column(unique = true, nullable = false)


private String username;
@Column(nullable = false)
private String password; // Added back for authentication

private String fullName;


private String email;

@Column(nullable = false)
private LocalDateTime createdAt = [Link]();
}
[Link]
package [Link];

import [Link];

public class LoginRequest {

@NotBlank(message = "Username is required")


private String username;

@NotBlank(message = "Password is required")


private String password;

// Getters and Setters


public String getUsername() {
return username;
}

public void setUsername(String username) {


[Link] = username;
}

public String getPassword() {


return password;
}

public void setPassword(String password) {


[Link] = password;
}
}
package [Link];

import [Link];

public class PortfolioItem {


private String symbol;
private int quantity;
private BigDecimal averagePrice;
private BigDecimal currentPrice;
private BigDecimal investmentValue;
private BigDecimal currentValue;
private BigDecimal profitLoss;
private BigDecimal profitLossPercentage;

// Constructors, Getters and Setters


public PortfolioItem() {
}

public PortfolioItem(String symbol, int quantity, BigDecimal averagePrice, BigDecimal


currentPrice) {
[Link] = symbol;
[Link] = quantity;
[Link] = averagePrice;
[Link] = currentPrice;
calculateValues();
}

private void calculateValues() {


[Link] = [Link]([Link](quantity));
[Link] = [Link]([Link](quantity));
[Link] = [Link](investmentValue);
[Link] = [Link]([Link]) != 0
? [Link](investmentValue, 4,
BigDecimal.ROUND_HALF_UP).multiply([Link](100))
: [Link];
}

// Getters and Setters


public String getSymbol() {
return symbol;
}

public void setSymbol(String symbol) {


[Link] = symbol;
}

public int getQuantity() {


return quantity;
}
public void setQuantity(int quantity) {
[Link] = quantity;
calculateValues();
}

public BigDecimal getAveragePrice() {


return averagePrice;
}

public void setAveragePrice(BigDecimal averagePrice) {


[Link] = averagePrice;
calculateValues();
}

public BigDecimal getCurrentPrice() {


return currentPrice;
}

public void setCurrentPrice(BigDecimal currentPrice) {


[Link] = currentPrice;
calculateValues();
}

public BigDecimal getInvestmentValue() {


return investmentValue;
}

public BigDecimal getCurrentValue() {


return currentValue;
}

public BigDecimal getProfitLoss() {


return profitLoss;
}

public BigDecimal getProfitLossPercentage() {


return profitLossPercentage;
}
}
package [Link];

import [Link];
import [Link];
import [Link];
import [Link];

public class
PortfolioRequest {

@NotBlank(message = "Stock symbol is required")


private String symbol;

@NotNull(message = "Quantity is required")


@Min(value = 1, message = "Quantity must be at least 1")
private Integer quantity;

@NotNull(message = "Price is required")


@Positive(message = "Price must be positive")
private Double averagePrice;

// Getters and Setters


public String getSymbol() {
return symbol;
}

public void setSymbol(String symbol) {


[Link] = symbol;
}

public Integer getQuantity() {


return quantity;
}

public void setQuantity(Integer quantity) {


[Link] = quantity;
}

public Double getAveragePrice() {


return averagePrice;
}

public void setAveragePrice(Double averagePrice) {


[Link] = averagePrice;
}
}
package [Link];
import [Link];
import [Link];

public class PortfolioSummary {


private final double totalValue;
private final double todaysGain;
private final double overallGain;
private final double gainPercentage;
private final List<PortfolioItem> items;

public PortfolioSummary(double totalValue, double todaysGain,


double overallGain, double gainPercentage,
List<PortfolioItem> items) {
[Link] = totalValue;
[Link] = todaysGain;
[Link] = overallGain;
[Link] = gainPercentage;
[Link] = items;
}

// Getters
public double getTotalValue() { return totalValue; }
public double getTodaysGain() { return todaysGain; }
public double getOverallGain() { return overallGain; }
public double getGainPercentage() { return gainPercentage; }
public List<PortfolioItem> getItems() { return items; }

// PortfolioItem inner class


public static class PortfolioItem {
private final String symbol;
private final int quantity;
private final double averagePrice;
private final double currentPrice;
private final double gain;
private final double gainPercentage;

public PortfolioItem(String symbol, int quantity,


double averagePrice, double currentPrice,
double gain, double gainPercentage) {
[Link] = symbol;
[Link] = quantity;
[Link] = averagePrice;
[Link] = currentPrice;
[Link] = gain;
[Link] = gainPercentage;
}

// Getters
public String getSymbol() { return symbol; }
public int getQuantity() { return quantity; }
public double getAveragePrice() { return averagePrice; }
public double getCurrentPrice() { return currentPrice; }
public double getGain() { return gain; }
public double getGainPercentage() { return gainPercentage; }
}
}
package [Link];

import [Link];

public class PredictionResult {

private String symbol;


private double currentPrice;
private double predictedPrice;
private String trend; // UP/DOWN
private double confidence; // 0-100
private double potentialGain; // percentage
private LocalDate predictionDate;
private LocalDate targetDate;

public PredictionResult(String symbol, double currentPrice, double predictedPrice, String s,


double confidence, double v, LocalDate now, LocalDate localDate) {
}

// Getters and Setters


public String getSymbol() {
return symbol;
}

public void setSymbol(String symbol) {


[Link] = symbol;
}

public double getCurrentPrice() {


return currentPrice;
}
public void setCurrentPrice(double currentPrice) {
[Link] = currentPrice;
}

public double getPredictedPrice() {


return predictedPrice;
}

public void setPredictedPrice(double predictedPrice) {


[Link] = predictedPrice;
}

public String getTrend() {


return trend;
}

public void setTrend(String trend) {


[Link] = trend;
}

public double getConfidence() {


return confidence;
}

public void setConfidence(double confidence) {


[Link] = confidence;
}

public double getPotentialGain() {


return potentialGain;
}

public void setPotentialGain(double potentialGain) {


[Link] = potentialGain;
}

public LocalDate getPredictionDate() {


return predictionDate;
}

public void setPredictionDate(LocalDate predictionDate) {


[Link] = predictionDate;
}
public LocalDate getTargetDate() {
return targetDate;
}

public void setTargetDate(LocalDate targetDate) {


[Link] = targetDate;
}
}
package [Link];

import [Link];
import [Link];
import [Link];

public class RegisterRequest {

@NotBlank(message = "Username is required")


@Size(min = 3, max = 20, message = "Username must be between 3 and 20 characters")
private String username;

@NotBlank(message = "Password is required")


@Size(min = 6, max = 40, message = "Password must be between 6 and 40 characters")
private String password;

@NotBlank(message = "Full name is required")


private String fullName;

@NotBlank(message = "Email is required")


@Email(message = "Email should be valid")
private String email;

// Getters and Setters


public String getUsername() {
return username;
}

public void setUsername(String username) {


[Link] = username;
}

public String getPassword() {


return password;
}
public void setPassword(String password) {
[Link] = password;
}

public String getFullName() {


return fullName;
}

public void setFullName(String fullName) {


[Link] = fullName;
}

public String getEmail() {


return email;
}

public void setEmail(String email) {


[Link] = email;
}
}
[Link]
package [Link];

import [Link];
import [Link];

@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public class BadRequestException extends RuntimeException {
public BadRequestException(String message) {
super(message);
}

public BadRequestException(String message, Throwable cause) {


super(message, cause);
}
}
package [Link];

public record ErrorResponse(


int status,
String message,
long timestamp
) {}
package [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

@ControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler([Link])
public ResponseEntity<ErrorResponse> handleBadRequest(
BadRequestException ex, WebRequest request) {
ErrorResponse response = new ErrorResponse(
HttpStatus.BAD_REQUEST.value(),
[Link](),
[Link]());
return [Link]().body(response);
}

@ExceptionHandler([Link])
public ResponseEntity<ErrorResponse> handleResourceNotFound(
ResourceNotFoundException ex, WebRequest request) {
ErrorResponse response = new ErrorResponse(
HttpStatus.NOT_FOUND.value(),
[Link](),
[Link]());
return [Link](HttpStatus.NOT_FOUND).body(response);
}

// Add generic exception handler (optional but recommended)


@ExceptionHandler([Link])
public ResponseEntity<ErrorResponse> handleGlobalException(
Exception ex, WebRequest request) {
ErrorResponse response = new ErrorResponse(
HttpStatus.INTERNAL_SERVER_ERROR.value(),
"An unexpected error occurred",
[Link]());
return [Link]().body(response);
}
}
package [Link];
import [Link];
import [Link];

@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
private final String resourceName;
private final String fieldName;
private final Object fieldValue;

public ResourceNotFoundException(String resourceName, String fieldName, Object


fieldValue) {
super([Link]("%s not found with %s : '%s'", resourceName, fieldName, fieldValue));
[Link] = resourceName;
[Link] = fieldName;
[Link] = fieldValue;
}

public String getResourceName() {


return resourceName;
}

public String getFieldName() {


return fieldName;
}

public Object getFieldValue() {


return fieldValue;
}
}
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];

@Component
public class DataLoader {

private final StockDataService stockDataService;

public DataLoader(StockDataService stockDataService) {


[Link] = stockDataService;
}
@PostConstruct
public void importData() {
String filePath = "src/main/resources/static/data/[Link]"; // path to your CSV file
String symbol = "NABIL"; // the stock symbol

try {
[Link](filePath, symbol);
[Link]("Stock data imported successfully.");
} catch (IOException e) {
[Link]();
}
}
}
repository
package [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

import [Link];

@Repository
public interface PortfolioRepository extends JpaRepository<Portfolio, Long> {

List<Portfolio> findByUser(User user);

List<Portfolio> findByUserAndSymbol(User user, String symbol);

@Query("SELECT p FROM Portfolio p WHERE [Link] = :user GROUP BY [Link]")


List<Portfolio> findDistinctByUser(User user);

@Query("SELECT [Link] FROM Portfolio p WHERE [Link] = :user GROUP BY [Link]")


List<String> findDistinctSymbolsByUser(User user);

@Query("SELECT SUM([Link]) FROM Portfolio p WHERE [Link] = :user AND [Link] =


:symbol AND [Link] = 'BUY'")
Integer sumBoughtQuantityByUserAndSymbol(User user, String symbol);

@Query("SELECT SUM([Link]) FROM Portfolio p WHERE [Link] = :user AND [Link] =


:symbol AND [Link] = 'SELL'")
Integer sumSoldQuantityByUserAndSymbol(User user, String symbol);

@Query("SELECT COALESCE(SUM([Link] * [Link]), 0) FROM Portfolio p WHERE


[Link] = :user AND [Link] = :symbol AND [Link] = 'BUY'")
Double sumInvestmentByUserAndSymbol(User user, String symbol);
}
package [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

import [Link];
import [Link];

@Repository
public interface StockDataRepository extends JpaRepository<StockData, Long> {

List<StockData> findBySymbolOrderByDateDesc(String symbol);

@Query("SELECT s FROM StockData s WHERE [Link] = :symbol ORDER BY [Link] DESC


LIMIT :limit")
List<StockData> findTopNBySymbolOrderByDateDesc(String symbol, int limit);

StockData findTopBySymbolOrderByDateDesc(String symbol);

StockData findBySymbolAndDate(String symbol, LocalDate date);

@Query("SELECT DISTINCT [Link] FROM StockData s")


List<String> findAllDistinctSymbols();

@Query("SELECT s FROM StockData s WHERE [Link] = (SELECT MAX([Link]) FROM


StockData s2) ORDER BY [Link] DESC LIMIT :count")
List<StockData> getTopGainers(int count);

@Query("SELECT s FROM StockData s WHERE [Link] = (SELECT MAX([Link]) FROM


StockData s2) ORDER BY [Link] ASC LIMIT :count")
List<StockData> getTopLosers(int count);

List<StockData> findTop60BySymbolOrderByDateDesc(String symbol);

long countBySymbol(String symbol);


@Modifying
@Query("DELETE FROM StockData s WHERE [Link] = :symbol")
void deleteBySymbol(String symbol);

List<StockData> findBySymbol(String symbol);

}
package [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

import [Link];

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
Optional<User> findByEmail(String email);
Boolean existsByUsername(String username);
Boolean existsByEmail(String email);

@Query("SELECT u FROM User u WHERE [Link] = :username OR [Link] = :email")


Optional<User> findByUsernameOrEmail(@Param("username") String username,
@Param("email") String email);
}

[Link]
package [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link].Nd4j;
import [Link];
import [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

@Service
public class LstmPredictionService {

private final StockDataRepository stockDataRepository;

@Value("${[Link]}")
private String modelDirectory;

public LstmPredictionService(StockDataRepository stockDataRepository) {


[Link] = stockDataRepository;
}

public PredictionResult predictStock(String symbol) {


// Get historical data
List<StockData> historicalData = stockDataRepository
.findTop60BySymbolOrderByDateDesc(symbol);
[Link](historicalData);
[Link]("Fetched data size: " + [Link]());
for (StockData data : historicalData) {
[Link]([Link]() + " - " + [Link]());
}

if ([Link]() < 60) {


throw new IllegalArgumentException("Not enough historical data for prediction");
}

// Preprocess data
double[] normalizedData = normalizeData(historicalData);

// Load model
MultiLayerNetwork model = loadModel(symbol);

// Prepare input
INDArray input = [Link](normalizedData, new int[]{1, 60, 1});

// Make prediction
INDArray output = [Link](input);
double predictedValue = [Link](0);

// Post-process prediction
double min =
[Link]().mapToDouble(StockData::getClosingPrice).min().orElse(0);
double max =
[Link]().mapToDouble(StockData::getClosingPrice).max().orElse(1);
double predictedPrice = predictedValue * (max - min) + min;

// Create result
double currentPrice = [Link](0).getClosingPrice();
double confidence = calculateConfidence(historicalData, predictedPrice);

return new PredictionResult(


symbol,
currentPrice,
predictedPrice,
predictedPrice > currentPrice ? "UP" : "DOWN",
confidence,
((predictedPrice - currentPrice) / currentPrice) * 100,
[Link](),
[Link]().plusDays(7)
);
}

private double[] normalizeData(List<StockData> data) {


double min = [Link]().mapToDouble(StockData::getClosingPrice).min().orElse(0);
double max = [Link]().mapToDouble(StockData::getClosingPrice).max().orElse(1);

return [Link]()
.mapToDouble(d -> ([Link]() - min) / (max - min))
.toArray();
}

private MultiLayerNetwork loadModel(String symbol) {


try {
return [Link](new File(modelDirectory, symbol + ".zip"));
} catch (IOException e) {
throw new RuntimeException("Failed to load model for symbol: " + symbol, e);
}
}

private double calculateConfidence(List<StockData> historicalData, double predictedPrice) {


// Simple confidence calculation based on recent volatility
double sum = 0;
double count = 0;
for (int i = 0; i < [Link]() - 1; i++) {
double change = [Link]([Link](i).getClosingPrice() -
[Link](i + 1).getClosingPrice());
sum += change;
count++;
}

double avgChange = sum / count;


double diff = [Link](predictedPrice - [Link](0).getClosingPrice());

// Higher confidence when prediction is within average volatility range


return [Link](100, 80 + (20 * (1 - (diff / (avgChange * 3)))));
}
}
package [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

import [Link];
import [Link];

@Service
public class PortfolioService {

private final PortfolioRepository portfolioRepository;


private final UserRepository userRepository;
private final StockDataService stockDataService;

public PortfolioService(PortfolioRepository portfolioRepository,


UserRepository userRepository,
StockDataService stockDataService) {
[Link] = portfolioRepository;
[Link] = userRepository;
[Link] = stockDataService;
}
@Transactional
public void addStockToPortfolio(Long userId, String symbol, int quantity, double averagePrice)
{
User user = [Link](userId)
.orElseThrow(() -> new ResourceNotFoundException("User", "id", userId));

Portfolio portfolio = new Portfolio();


[Link](user);
[Link](symbol);
[Link](quantity);
[Link](averagePrice);
[Link]("BUY");
[Link](quantity * averagePrice);

[Link](portfolio);
}

@Transactional
public void removeStockFromPortfolio(Long userId, String symbol, int quantity) {
User user = [Link](userId)
.orElseThrow(() -> new ResourceNotFoundException("User", "id", userId));

int currentQuantity = getAvailableQuantity(user, symbol);


if (currentQuantity < quantity) {
throw new IllegalArgumentException("Not enough shares to sell");
}

Portfolio portfolio = new Portfolio();


[Link](user);
[Link](symbol);
[Link](quantity);
[Link]([Link](symbol));
[Link]("SELL");
[Link](quantity * [Link]());

[Link](portfolio);
}

@Transactional(readOnly = true)
public PortfolioSummary getUserPortfolio(Long userId) {
User user = [Link](userId)
.orElseThrow(() -> new ResourceNotFoundException("User", "id", userId));
List<String> symbols = [Link](user);

// Using a container object to hold our accumulators


PortfolioSummaryContainer container = new PortfolioSummaryContainer();

List<[Link]> items = [Link]()


.map(symbol -> processSymbol(user, symbol, container))
.collect([Link]());

double overallGain = [Link] - [Link];


double gainPercentage = [Link] > 0 ?
(overallGain / [Link]) * 100 : 0;

return new PortfolioSummary(


[Link],
[Link],
overallGain,
gainPercentage,
items
);
}

private [Link] processSymbol(User user, String symbol,


PortfolioSummaryContainer container) {
int bought = [Link](user, symbol);
int sold = [Link](user, symbol);
int available = bought - sold;

double currentPrice = [Link](symbol);


double investment = [Link](user, symbol);
double avgPrice = bought > 0 ? investment / bought : 0;

double value = available * currentPrice;


double gain = value - (available * avgPrice);
double gainPercentage = (available * avgPrice) != 0 ? (gain / (available * avgPrice)) * 100 : 0;

// Update container values


[Link] += value;
[Link] += (available * avgPrice);

// Calculate today's gain with null check


List<StockData> history = [Link](symbol, 2);
double yesterdayPrice = [Link]() > 1 ? [Link](1).getClosingPrice() : currentPrice;
[Link] += available * (currentPrice - yesterdayPrice);
return new [Link](
symbol,
available,
avgPrice,
currentPrice,
gain,
gainPercentage
);
}

private int getAvailableQuantity(User user, String symbol) {


Integer bought = [Link](user, symbol);
Integer sold = [Link](user, symbol);
return (bought != null ? bought : 0) - (sold != null ? sold : 0);
}

// Helper container class to hold accumulated values


private static class PortfolioSummaryContainer {
double totalValue = 0;
double totalInvestment = 0;
double todaysGain = 0;
}
}
package [Link];

import [Link];
import [Link];
import [Link];
import [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

@Service
public class StockDataService {

private final StockDataRepository stockDataRepository;

public StockDataService(StockDataRepository stockDataRepository) {


[Link] = stockDataRepository;
}

@Transactional(readOnly = true)
public List<StockData> getHistoricalData(String symbol, int days) {
return [Link](symbol, days);
}

@Transactional(readOnly = true)
public StockData getLatestData(String symbol) {
return [Link](symbol);
}

@Transactional(readOnly = true)
public List<StockData> getTopGainers(int count) {
return [Link](count);
}

@Transactional(readOnly = true)
public List<StockData> getTopLosers(int count) {
return [Link](count);
}

@Transactional(readOnly = true)
public List<String> getAllSymbols() {
return [Link]();
}

@Transactional
public void updateStockData(List<StockData> stockDataList) {
[Link](stockDataList);
}

@Transactional(readOnly = true)
public Double getCurrentPrice(String symbol) {
StockData latest = [Link](symbol);
return latest != null ? [Link]() : 0.0;
}

// === NEW METHOD: Import stock data from CSV ===


@Transactional
public void importStockDataFromCsv(String filePath, String symbol) throws IOException {
List<StockData> stockDataList = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;

// Skip CSV header


[Link]();

while ((line = [Link]()) != null) {


String[] tokens = [Link](",");

// Make sure we have enough columns


if ([Link] < 8) {
continue; // skip incomplete rows
}

// Parse data - adjust column indexes as per your CSV format


LocalDate date = [Link](tokens[0].trim()); // e.g. "2025-08-05"
double openingPrice = [Link](tokens[1].trim());
double closingPrice = [Link](tokens[2].trim());
double highPrice = [Link](tokens[3].trim());
double lowPrice = [Link](tokens[4].trim());
long volume = [Link](tokens[5].trim());
double changeAmount = [Link](tokens[6].trim());
double changePercentage = [Link](tokens[7].trim());

// Optional: Parse technical indicators if present in CSV


double movingAverage5 = [Link] > 8 ? [Link](tokens[8].trim()) :
0.0;
double movingAverage20 = [Link] > 9 ? [Link](tokens[9].trim()) :
0.0;
double movingAverage50 = [Link] > 10 ?
[Link](tokens[10].trim()) : 0.0;
double rsi14 = [Link] > 11 ? [Link](tokens[11].trim()) : 0.0;
double macd = [Link] > 12 ? [Link](tokens[12].trim()) : 0.0;
double bollingerUpper = [Link] > 13 ? [Link](tokens[13].trim()) :
0.0;
double bollingerLower = [Link] > 14 ? [Link](tokens[14].trim()) :
0.0;

// Create StockData entity and set fields


StockData stockData = new StockData();
[Link](symbol);
[Link](date);
[Link](openingPrice);
[Link](closingPrice);
[Link](highPrice);
[Link](lowPrice);
[Link](volume);
[Link](changeAmount);
[Link](changePercentage);
stockData.setMovingAverage5(movingAverage5);
stockData.setMovingAverage20(movingAverage20);
stockData.setMovingAverage50(movingAverage50);
stockData.setRsi14(rsi14);
[Link](macd);
[Link](bollingerUpper);
[Link](bollingerLower);

[Link](stockData);
}
}

// Save all records in batch


[Link](stockDataList);
}

@Transactional
public void ensureMinimumData(String symbol, int minDays) {
long count = [Link](symbol);
if (count < minDays) {
// Add sample data if we don't have enough
double basePrice = switch (symbol) {
case "NABIL" -> 2000.0;
case "NICA" -> 1500.0;
case "NBL" -> 1200.0;
case "SCB" -> 1800.0;
case "HIDCL" -> 500.0;
case "GBIME" -> 800.0;
default -> 1000.0;
};

// Delete existing data if any


List<StockData> existing = [Link](symbol);
if (![Link]()) {
[Link](existing);
}
}}}
package [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

@Service
public class UserService {

private final UserRepository userRepository;


private final PasswordEncoder passwordEncoder;

public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder) {


[Link] = userRepository;
[Link] = passwordEncoder;
}

@Transactional
public User createUser(RegisterRequest registerRequest) {
if ([Link]([Link]())) {
throw new BadRequestException("Username already in use");
}

if ([Link]([Link]())) {
throw new BadRequestException("Email already in use");
}

User user = new User();


[Link]([Link]());
[Link]([Link]([Link]()));
[Link]([Link]());
[Link]([Link]());

return [Link](user);
}

@Transactional(readOnly = true)
public UserPrincipal loadUserById(Long id) {
User user = [Link](id)
.orElseThrow(() -> new ResourceNotFoundException("User", "id", id));

return [Link](user);
}

public boolean existsByUsername(String username) {


return [Link](username);
}
public boolean existsByEmail(String email) {
return [Link](email);
}
}

7Util
// src/main/java/com/nepse/util/[Link]
package [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

import [Link];
import [Link];
import [Link];

@Component
public class DataInitializer {

private final StockDataRepository stockDataRepository;

@Autowired
public DataInitializer(StockDataRepository stockDataRepository) {
[Link] = stockDataRepository;
}

@PostConstruct
@Transactional
public void init() {
// Ensure we have data for key symbols
ensureSymbolData("NABIL", 2000.0, 60);
ensureSymbolData("NICA", 1500.0, 60);
ensureSymbolData("NBL", 1200.0, 60);
ensureSymbolData("SCB", 1800.0, 60);
ensureSymbolData("HIDCL", 500.0, 60);
ensureSymbolData("GBIME", 800.0, 60);

private void ensureSymbolData(String symbol, double startPrice, int days) {


long count = [Link](symbol);
if (count < days) {
// Remove existing incomplete data
if (count > 0) {
[Link](symbol);
}

// Add new sample data


addSampleData(symbol, startPrice, days);
[Link]("Added " + days + " days of data for " + symbol);
}
}

private void addSampleData(String symbol, double startPrice, int days) {


List<StockData> data = new ArrayList<>();
LocalDate startDate = [Link]().minusDays(days);
double price = startPrice;

for (int i = 0; i < days; i++) {


double change = ([Link]() - 0.5) * 50; // Random change between -50 to +50
price += change;

StockData stock = new StockData();


[Link](symbol);
[Link]([Link](i));
[Link](price - 10);
[Link](price);
[Link](price + 5);
[Link](price - 15);
[Link](100000 + (long)([Link]() * 50000));
[Link](change);
[Link]((change / (price - change)) * 100);

// Add technical indicators


stock.setMovingAverage5(calculateMovingAverage(data, 5, price));
stock.setMovingAverage20(calculateMovingAverage(data, 20, price));
stock.setMovingAverage50(calculateMovingAverage(data, 50, price));

[Link](stock);
}

[Link](data);
}

private double calculateMovingAverage(List<StockData> data, int period, double currentPrice)


{
if ([Link]() < period - 1) {
return currentPrice;
}

double sum = currentPrice;


int count = 1;
for (int i = [Link]() - 1; i >= [Link](0, [Link]() - period + 1); i--) {
sum += [Link](i).getClosingPrice();
count++;
}
return sum / count;
}
}
package [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

import [Link];
import [Link];

public class ModelUtils {

private static final Logger logger = [Link]([Link]);

/**
* Saves the LSTM model and its normalizer to disk
*
* @param model The trained LSTM model
* @param normalizer The data normalizer used with the model
* @param modelFile The file to save the model to
* @throws IOException If there's an error saving the files
*/
public static void saveModel(MultiLayerNetwork model,
NormalizerMinMaxScaler normalizer,
File modelFile) throws IOException {
// Create parent directories if they don't exist
[Link]().mkdirs();

// Save the model


[Link](model, modelFile, true);
[Link]("Saved model to: {}", [Link]());

// Save the normalizer


File normalizerFile = new File([Link](),
[Link]().replace(".zip", "-[Link]"));
[Link]().write(normalizer, normalizerFile);
[Link]("Saved normalizer to: {}", [Link]());
}

/**
* Loads a trained LSTM model from disk
*
* @param modelFile The file containing the saved model
* @return The loaded MultiLayerNetwork model
* @throws IOException If there's an error loading the model
*/
public static MultiLayerNetwork loadModel(File modelFile) throws IOException {
if (![Link]()) {
throw new IOException("Model file not found: " + [Link]());
}

MultiLayerNetwork model = [Link](modelFile);


[Link]("Loaded model from: {}", [Link]());
return model;
}
/**
* Loads the normalizer used with a specific model
*
* @param modelFile The model file path
* @return The loaded NormalizerMinMaxScaler
* @throws IOException If there's an error loading the normalizer
*/
public static NormalizerMinMaxScaler loadNormalizer(File modelFile) throws Exception {
File normalizerFile = new File([Link](),
[Link]().replace(".zip", "-[Link]"));

if (![Link]()) {
throw new IOException("Normalizer file not found: " + [Link]());
}

return [Link]().restore(normalizerFile);
}

/**
* Checks if a trained model exists for a given symbol
*
* @param modelDir The directory containing models
* @param symbol The stock symbol to check
* @return true if model exists, false otherwise
*/
public static boolean modelExists(File modelDir, String symbol) {
File modelFile = new File(modelDir, symbol + ".zip");
File normalizerFile = new File(modelDir, symbol + "-[Link]");
return [Link]() && [Link]();
}

/**
* Deletes model and normalizer files for a given symbol
*
* @param modelDir The directory containing models
* @param symbol The stock symbol to delete
* @return true if files were deleted, false otherwise
*/
public static boolean deleteModel(File modelDir, String symbol) {
File modelFile = new File(modelDir, symbol + ".zip");
File normalizerFile = new File(modelDir, symbol + "-[Link]");

boolean modelDeleted = [Link]() && [Link]();


boolean normalizerDeleted = [Link]() && [Link]();

return modelDeleted || normalizerDeleted;


}
}
and finally the main class
package [Link];

import [Link];
import [Link];
@SpringBootApplication
public class StockPredictionApplication {
public static void main(String[] args) {
[Link]([Link], args);
}
}

You might also like