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:
@ -6,6 +6,7 @@ namespace StockHistory.Services
|
|||||||
{
|
{
|
||||||
Task GenerateStockVision();
|
Task GenerateStockVision();
|
||||||
Task<List<SglStockEquity>> GetAllAsync();
|
Task<List<SglStockEquity>> GetAllAsync();
|
||||||
|
List<SglStockEquity> GetLatestSoldInfoAsync();
|
||||||
Task<List<SglStockEquity>> GetAllAsync(DateTime equityDate);
|
Task<List<SglStockEquity>> GetAllAsync(DateTime equityDate);
|
||||||
Task<List<SglStockEquity>> GetByCodeAsync(string stockCode);
|
Task<List<SglStockEquity>> GetByCodeAsync(string stockCode);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ namespace StockHistory.Services
|
|||||||
{
|
{
|
||||||
Task<List<StockEquity>> GenerateStockVision();
|
Task<List<StockEquity>> GenerateStockVision();
|
||||||
Task<List<StockEquity>> GetAllAsync();
|
Task<List<StockEquity>> GetAllAsync();
|
||||||
|
Task<List<StockEquity>> GetLatestSoldInfoAsync();
|
||||||
Task<List<StockEquity>> GetAllAsync(DateTime equityDate);
|
Task<List<StockEquity>> GetAllAsync(DateTime equityDate);
|
||||||
Task<List<StockEquity>> GetByCodeAsync(string stockCode);
|
Task<List<StockEquity>> GetByCodeAsync(string stockCode);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ namespace StockHistory.Services
|
|||||||
{
|
{
|
||||||
Task AddAsync(TransactionNote transactionNote);
|
Task AddAsync(TransactionNote transactionNote);
|
||||||
Task DeleteAsync(int id);
|
Task DeleteAsync(int id);
|
||||||
|
Task<List<string>> GetAllExistingStockCodes();
|
||||||
Task<List<TransactionNote>> GetAllAsync();
|
Task<List<TransactionNote>> GetAllAsync();
|
||||||
Task<TransactionNote?> GetByIdAsync(int id);
|
Task<TransactionNote?> GetByIdAsync(int id);
|
||||||
Task<TransactionNote?> GetByIndexAsync(string stockCode, DateTime transDate);
|
Task<TransactionNote?> GetByIndexAsync(string stockCode, DateTime transDate);
|
||||||
|
|||||||
@ -36,6 +36,27 @@ namespace StockHistory.Services
|
|||||||
.OrderBy(s => s.Bought)
|
.OrderBy(s => s.Bought)
|
||||||
.ToListAsync();
|
.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>
|
/// <summary>
|
||||||
/// Skapar en ny lista med aktieinnehav baserat på transaktionsnoteringar.
|
/// Skapar en ny lista med aktieinnehav baserat på transaktionsnoteringar.
|
||||||
/// Den rensar först den befintliga listan och bygger sedan upp den igen genom att
|
/// Den rensar först den befintliga listan och bygger sedan upp den igen genom att
|
||||||
|
|||||||
@ -36,6 +36,48 @@ public class StockEquityServices : IStockEquityServices
|
|||||||
.OrderBy(s => s.Bought)
|
.OrderBy(s => s.Bought)
|
||||||
.ToListAsync();
|
.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>
|
/// <summary>
|
||||||
/// Skapar en ny lista med aktieinnehav baserat på transaktionsnoteringar.
|
/// Skapar en ny lista med aktieinnehav baserat på transaktionsnoteringar.
|
||||||
/// Den rensar först den befintliga listan och bygger sedan upp den igen genom att
|
/// Den rensar först den befintliga listan och bygger sedan upp den igen genom att
|
||||||
|
|||||||
@ -48,6 +48,18 @@ public class TransactionNotesServices : ITransactionNotesServices
|
|||||||
return await _dbContext.TransactionNotes.Where(t => t.StockCode == stockCode).ToListAsync();
|
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)
|
public async Task AddAsync(TransactionNote transactionNote)
|
||||||
{
|
{
|
||||||
using var scope = _provider.CreateScope();
|
using var scope = _provider.CreateScope();
|
||||||
|
|||||||
@ -7,12 +7,16 @@ namespace StockHistory;
|
|||||||
public partial class frmStockHistoryAnalyse : Form
|
public partial class frmStockHistoryAnalyse : Form
|
||||||
{
|
{
|
||||||
private readonly IStockEquityServices _equityServices;
|
private readonly IStockEquityServices _equityServices;
|
||||||
|
private readonly ITransactionNotesServices _transactionNotesServices;
|
||||||
|
List<string> stockList = new();
|
||||||
|
|
||||||
public frmStockHistoryAnalyse(IStockEquityServices equityServices)
|
public frmStockHistoryAnalyse(IStockEquityServices equityServices, ITransactionNotesServices transactionNotesServices)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
_equityServices = equityServices;
|
_equityServices = equityServices;
|
||||||
|
_transactionNotesServices = transactionNotesServices;
|
||||||
lwStocks.EnableSmartSorting();
|
lwStocks.EnableSmartSorting();
|
||||||
|
lwStockHistory.EnableSmartSorting();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,6 +42,8 @@ public partial class frmStockHistoryAnalyse : Form
|
|||||||
|
|
||||||
private async Task LoadStockListAsync(DateTime equityDate)
|
private async Task LoadStockListAsync(DateTime equityDate)
|
||||||
{
|
{
|
||||||
|
stockList = await _transactionNotesServices.GetAllExistingStockCodes();
|
||||||
|
|
||||||
|
|
||||||
var stocks = await _equityServices.GetAllAsync(equityDate);
|
var stocks = await _equityServices.GetAllAsync(equityDate);
|
||||||
// var stocks = await _equityServices.GetAllAsync();
|
// var stocks = await _equityServices.GetAllAsync();
|
||||||
@ -57,8 +63,11 @@ public partial class frmStockHistoryAnalyse : Form
|
|||||||
{
|
{
|
||||||
if (t.StockCode != equityTemp.StockCode)
|
if (t.StockCode != equityTemp.StockCode)
|
||||||
{
|
{
|
||||||
|
stockList.Remove(t.StockCode);
|
||||||
|
|
||||||
if (equityTemp.StockCode != "Total")
|
if (equityTemp.StockCode != "Total")
|
||||||
{
|
{
|
||||||
|
|
||||||
var item = new ListViewItem(equityTemp.StockCode);
|
var item = new ListViewItem(equityTemp.StockCode);
|
||||||
item.SubItems.Add(equityTemp.Bought.ToString());
|
item.SubItems.Add(equityTemp.Bought.ToString());
|
||||||
item.SubItems.Add(equityTemp.Quantity.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.Quantity.ToString());
|
||||||
l_item.SubItems.Add(equityTemp.BoughtPrice.ToString());
|
l_item.SubItems.Add(equityTemp.BoughtPrice.ToString());
|
||||||
l_item.SubItems.Add((equityTemp.TotalValue).ToString("C"));
|
l_item.SubItems.Add((equityTemp.TotalValue).ToString("C"));
|
||||||
|
stockList.Remove(l_item.Text);
|
||||||
lwStocks.Items.Add(l_item);
|
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)
|
private void lwStocks_MouseClick(object sender, MouseEventArgs e)
|
||||||
{
|
{
|
||||||
@ -159,4 +166,35 @@ public partial class frmStockHistoryAnalyse : Form
|
|||||||
}
|
}
|
||||||
lwStockHistory.Refresh();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -285,6 +285,7 @@ public partial class frmStockHistoryInit : Form
|
|||||||
}
|
}
|
||||||
if (line.StartsWith("Kurs"))
|
if (line.StartsWith("Kurs"))
|
||||||
{
|
{
|
||||||
|
trans.Currency = line.Split(" ", StringSplitOptions.RemoveEmptyEntries)[1];
|
||||||
trans.StockPrice = decimal.Parse(line.Split(" ", StringSplitOptions.RemoveEmptyEntries)[2]);
|
trans.StockPrice = decimal.Parse(line.Split(" ", StringSplitOptions.RemoveEmptyEntries)[2]);
|
||||||
}
|
}
|
||||||
if (line.StartsWith("Antal"))
|
if (line.StartsWith("Antal"))
|
||||||
|
|||||||
Reference in New Issue
Block a user