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);
}
}