Rättat till inläsning så att både shb och avanza notor kan läsas in från csv-fil. Rättat historiska aktier

This commit is contained in:
2026-09-06 23:00:18 +02:00
parent 56ee27aab9
commit 9b010ed388
8 changed files with 121 additions and 4 deletions

View File

@ -6,6 +6,7 @@ namespace StockHistory.Services
{
Task GenerateStockVision();
Task<List<SglStockEquity>> GetAllAsync();
List<SglStockEquity> GetLatestSoldInfoAsync();
Task<List<SglStockEquity>> GetAllAsync(DateTime equityDate);
Task<List<SglStockEquity>> GetByCodeAsync(string stockCode);
}

View File

@ -6,6 +6,7 @@ namespace StockHistory.Services
{
Task<List<StockEquity>> GenerateStockVision();
Task<List<StockEquity>> GetAllAsync();
Task<List<StockEquity>> GetLatestSoldInfoAsync();
Task<List<StockEquity>> GetAllAsync(DateTime equityDate);
Task<List<StockEquity>> GetByCodeAsync(string stockCode);
}

View File

@ -6,6 +6,7 @@ namespace StockHistory.Services
{
Task AddAsync(TransactionNote transactionNote);
Task DeleteAsync(int id);
Task<List<string>> GetAllExistingStockCodes();
Task<List<TransactionNote>> GetAllAsync();
Task<TransactionNote?> GetByIdAsync(int id);
Task<TransactionNote?> GetByIndexAsync(string stockCode, DateTime transDate);

View File

@ -36,6 +36,27 @@ namespace StockHistory.Services
.OrderBy(s => s.Bought)
.ToListAsync();
}
public List<SglStockEquity> GetLatestSoldInfoAsync()
{
var today = DateTime.Today;
var query =
from s in _dbContext.SglStocks
where s.Sold < today
group s by s.StockCode into g
let maxSold = g.Max(x => x.Sold)
let minBought = g.Where(x => x.Sold == maxSold).Min(x => x.BoughtPrice)
from row in g
where row.Sold == maxSold && row.BoughtPrice == minBought
select row;
var result = query.ToList();
return result;
}
/// <summary>
/// Skapar en ny lista med aktieinnehav baserat på transaktionsnoteringar.
/// Den rensar först den befintliga listan och bygger sedan upp den igen genom att

View File

@ -36,6 +36,48 @@ public class StockEquityServices : IStockEquityServices
.OrderBy(s => s.Bought)
.ToListAsync();
}
public async Task<List<StockEquity>> GetLatestSoldInfoAsync()
{
var today = DateTime.Today;
var maxPerCode = _dbContext.Stocks
.Where(s => s.Sold < today)
.GroupBy(s => s.StockCode)
.Select(g => new { StockCode = g.Key, MaxSold = g.Max(x => x.Sold) });
var minBoughtPerCodeAndSold = _dbContext.Stocks
.Where(s => s.Sold < today)
.Join(maxPerCode,
s => new { s.StockCode, s.Sold },
m => new { m.StockCode, Sold = m.MaxSold },
(s, m) => new { s.StockCode, s.Sold, s.BoughtPrice })
.GroupBy(x => new { x.StockCode, x.Sold })
.Select(g => new { g.Key.StockCode, g.Key.Sold, MinBought = g.Min(x => (double)x.BoughtPrice) });
var result = from s in _dbContext.Stocks
where s.Sold < today
join mm in minBoughtPerCodeAndSold
on new { s.StockCode, s.Sold, BoughtPrice = (double)s.BoughtPrice }
equals new { mm.StockCode, Sold = mm.Sold, BoughtPrice = mm.MinBought }
select s;
return await result.ToListAsync();
//var query =
// from s in _dbContext.Stocks
// where s.Sold < today
// group s by s.StockCode into g
// let maxSold = g.Max(x => x.Sold)
// let minBought = g.Where(x => x.Sold == maxSold).Min(x => x.BoughtPrice)
// from row in g
// where row.Sold == maxSold && row.BoughtPrice == minBought
// select row;
//return await query.ToListAsync();
}
/// <summary>
/// Skapar en ny lista med aktieinnehav baserat på transaktionsnoteringar.
/// Den rensar först den befintliga listan och bygger sedan upp den igen genom att

View File

@ -48,6 +48,18 @@ public class TransactionNotesServices : ITransactionNotesServices
return await _dbContext.TransactionNotes.Where(t => t.StockCode == stockCode).ToListAsync();
}
public async Task<List<string?>> GetAllExistingStockCodes()
{
List<string?> stockCodes = new List<string?>();
stockCodes = await _dbContext.TransactionNotes
.Select(t => t.StockCode)
.Distinct()
.ToListAsync();
return stockCodes;
}
public async Task AddAsync(TransactionNote transactionNote)
{
using var scope = _provider.CreateScope();

View File

@ -7,12 +7,16 @@ namespace StockHistory;
public partial class frmStockHistoryAnalyse : Form
{
private readonly IStockEquityServices _equityServices;
private readonly ITransactionNotesServices _transactionNotesServices;
List<string> stockList = new();
public frmStockHistoryAnalyse(IStockEquityServices equityServices)
public frmStockHistoryAnalyse(IStockEquityServices equityServices, ITransactionNotesServices transactionNotesServices)
{
InitializeComponent();
_equityServices = equityServices;
_transactionNotesServices = transactionNotesServices;
lwStocks.EnableSmartSorting();
lwStockHistory.EnableSmartSorting();
}
@ -38,6 +42,8 @@ public partial class frmStockHistoryAnalyse : Form
private async Task LoadStockListAsync(DateTime equityDate)
{
stockList = await _transactionNotesServices.GetAllExistingStockCodes();
var stocks = await _equityServices.GetAllAsync(equityDate);
// var stocks = await _equityServices.GetAllAsync();
@ -57,8 +63,11 @@ public partial class frmStockHistoryAnalyse : Form
{
if (t.StockCode != equityTemp.StockCode)
{
stockList.Remove(t.StockCode);
if (equityTemp.StockCode != "Total")
{
var item = new ListViewItem(equityTemp.StockCode);
item.SubItems.Add(equityTemp.Bought.ToString());
item.SubItems.Add(equityTemp.Quantity.ToString());
@ -87,6 +96,7 @@ public partial class frmStockHistoryAnalyse : Form
l_item.SubItems.Add(equityTemp.Quantity.ToString());
l_item.SubItems.Add(equityTemp.BoughtPrice.ToString());
l_item.SubItems.Add((equityTemp.TotalValue).ToString("C"));
stockList.Remove(l_item.Text);
lwStocks.Items.Add(l_item);
}
@ -100,10 +110,7 @@ public partial class frmStockHistoryAnalyse : Form
}
}
private void btnStockHistory_Click(object sender, EventArgs e)
{
}
private void lwStocks_MouseClick(object sender, MouseEventArgs e)
{
@ -159,4 +166,35 @@ public partial class frmStockHistoryAnalyse : Form
}
lwStockHistory.Refresh();
}
private async void btnStockHistory_Click(object sender, EventArgs e)
{
// var stockList = _transactionNotesServices.GetAllExistingStockCodes();
var histRecs = await _equityServices.GetLatestSoldInfoAsync();
if (histRecs != null)
{
lblVarning.Visible = false;
lwStockHistory.Items.Clear();
foreach (var histRec in histRecs)
{
if (stockList.Contains(histRec.StockCode))
{
var l_item = new ListViewItem(histRec.StockCode);
l_item.SubItems.Add(histRec.Bought.ToString());
l_item.SubItems.Add(histRec.Quantity.ToString());
l_item.SubItems.Add(histRec.BoughtPrice.ToString());
Debug.WriteLine(histRec.ToString());
var totval = (histRec.SoldQuant > 0) ? histRec.SoldQuant * histRec.SoldPrice - histRec.BoughtPrice * histRec.Quantity : histRec.BoughtPrice * histRec.Quantity;
l_item.SubItems.Add((totval).ToString("C"));
l_item.SubItems.Add((histRec.SoldQuant > 0) ? "B" : "K");
lwStockHistory.Items.Add(l_item);
stockList.Remove(histRec.StockCode);
}
}
}
lwStockHistory.Refresh();
}
}

View File

@ -285,6 +285,7 @@ public partial class frmStockHistoryInit : Form
}
if (line.StartsWith("Kurs"))
{
trans.Currency = line.Split(" ", StringSplitOptions.RemoveEmptyEntries)[1];
trans.StockPrice = decimal.Parse(line.Split(" ", StringSplitOptions.RemoveEmptyEntries)[2]);
}
if (line.StartsWith("Antal"))