diff --git a/ConsoleApp1/ConsoleApp1.csproj b/ConsoleApp1/ConsoleApp1.csproj
new file mode 100644
index 0000000..1d1ba3d
--- /dev/null
+++ b/ConsoleApp1/ConsoleApp1.csproj
@@ -0,0 +1,15 @@
+
+
+
+ Exe
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
diff --git a/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs
new file mode 100644
index 0000000..e885bd6
--- /dev/null
+++ b/ConsoleApp1/Program.cs
@@ -0,0 +1,9 @@
+// See https://aka.ms/new-console-template for more information
+
+using OemanTrader.Domain.Models;
+using OemanTrader.Domain.Services;
+using OemanTrader.EntityFramework;
+using OemanTrader.EntityFramework.Services;
+
+IDataService userService = new GenericDataService(new OemanTraderDbContextFactory());
+userService.Create(new User { UserName = "Test" }).Wait();
diff --git a/OemanTrader.Domain/Exceptions/InvalidSymbolException.cs b/OemanTrader.Domain/Exceptions/InvalidSymbolException.cs
new file mode 100644
index 0000000..bd47391
--- /dev/null
+++ b/OemanTrader.Domain/Exceptions/InvalidSymbolException.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.Domain.Exceptions
+{
+ public class InvalidSymbolException : Exception
+ {
+ public string Symbol { get; set; }
+ public InvalidSymbolException(string symbol)
+ {
+ Symbol = symbol;
+ }
+
+ public InvalidSymbolException(string symbol, string? message) : base(message)
+ {
+ Symbol = symbol;
+ }
+
+ public InvalidSymbolException(string symbol, string? message, Exception? innerException) : base(message, innerException)
+ {
+ Symbol = symbol;
+ }
+
+ }
+}
diff --git a/OemanTrader.Domain/Models/Account.cs b/OemanTrader.Domain/Models/Account.cs
new file mode 100644
index 0000000..242c4cd
--- /dev/null
+++ b/OemanTrader.Domain/Models/Account.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.Domain.Models
+{
+ public class Account : DomainObject
+ {
+ public User AccountHolder { get; set; }
+ public double Balance { get; set; }
+ public IEnumerable AssetTransactions { get; set; }
+ }
+}
diff --git a/OemanTrader.Domain/Models/Asset.cs b/OemanTrader.Domain/Models/Asset.cs
new file mode 100644
index 0000000..e801c33
--- /dev/null
+++ b/OemanTrader.Domain/Models/Asset.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.Domain.Models
+{
+ public class Asset
+ {
+ public string Symbol { get; set; }
+ public double PricePerShare { get; set; }
+ }
+}
diff --git a/OemanTrader.Domain/Models/AssetTransaction.cs b/OemanTrader.Domain/Models/AssetTransaction.cs
new file mode 100644
index 0000000..93ca62d
--- /dev/null
+++ b/OemanTrader.Domain/Models/AssetTransaction.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.Domain.Models
+{
+ public class AssetTransaction : DomainObject
+ {
+ public Account Account { get; set; }
+ public bool IsPurchase { get; set; }
+ public Asset Asset { get; set; }
+ public int ShareAmount { get; set; }
+ public DateTime DateProcessed { get; set; }
+ }
+}
diff --git a/OemanTrader.Domain/Models/DomainObject.cs b/OemanTrader.Domain/Models/DomainObject.cs
new file mode 100644
index 0000000..da738dc
--- /dev/null
+++ b/OemanTrader.Domain/Models/DomainObject.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.Domain.Models
+{
+ public class DomainObject
+ {
+ public int Id { get; set; }
+ }
+}
diff --git a/OemanTrader.Domain/Models/MajorIndex.cs b/OemanTrader.Domain/Models/MajorIndex.cs
new file mode 100644
index 0000000..c41d9dd
--- /dev/null
+++ b/OemanTrader.Domain/Models/MajorIndex.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.Domain.Models
+{
+ public enum MajorIndexType
+ {
+ DowJones,
+ Nasdaq,
+ SP500
+ }
+ public class MajorIndex
+ {
+ public string IndexName { get; set; }
+ public double Price { get; set; }
+ public double Changes { get; set; }
+ public MajorIndexType Type { get; set; }
+ }
+}
diff --git a/OemanTrader.Domain/Models/User.cs b/OemanTrader.Domain/Models/User.cs
new file mode 100644
index 0000000..b3552bf
--- /dev/null
+++ b/OemanTrader.Domain/Models/User.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.Domain.Models
+{
+ public class User : DomainObject
+ {
+ public string Email { get; set; }
+ public string UserName { get; set; }
+ public string Password { get; set; }
+ public DateTime DateJoined { get; set; }
+ }
+}
diff --git a/OemanTrader.Domain/OemanTrader.Domain.csproj b/OemanTrader.Domain/OemanTrader.Domain.csproj
new file mode 100644
index 0000000..132c02c
--- /dev/null
+++ b/OemanTrader.Domain/OemanTrader.Domain.csproj
@@ -0,0 +1,9 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
diff --git a/OemanTrader.Domain/Services/IDataService.cs b/OemanTrader.Domain/Services/IDataService.cs
new file mode 100644
index 0000000..1f8e2ab
--- /dev/null
+++ b/OemanTrader.Domain/Services/IDataService.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.Domain.Services
+{
+ public interface IDataService
+ {
+ Task> GetAll();
+ Task Get(int id);
+ Task Create(T entity);
+ Task Update(int Id, T entity);
+ Task Delete(int Id);
+ }
+}
diff --git a/OemanTrader.Domain/Services/IMajorIndexService.cs b/OemanTrader.Domain/Services/IMajorIndexService.cs
new file mode 100644
index 0000000..275b4e1
--- /dev/null
+++ b/OemanTrader.Domain/Services/IMajorIndexService.cs
@@ -0,0 +1,14 @@
+using OemanTrader.Domain.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.Domain.Services
+{
+ public interface IMajorIndexService
+ {
+ Task GetMajorIndex(MajorIndexType indexType);
+ }
+}
diff --git a/OemanTrader.Domain/Services/IStockPriceService.cs b/OemanTrader.Domain/Services/IStockPriceService.cs
new file mode 100644
index 0000000..e18792a
--- /dev/null
+++ b/OemanTrader.Domain/Services/IStockPriceService.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.Domain.Services
+{
+ public interface IStockPriceService
+ {
+ Task GetPrice(string symbol);
+ }
+}
diff --git a/OemanTrader.EntityFramework/Migrations/20220508202548_initial.Designer.cs b/OemanTrader.EntityFramework/Migrations/20220508202548_initial.Designer.cs
new file mode 100644
index 0000000..20c64f6
--- /dev/null
+++ b/OemanTrader.EntityFramework/Migrations/20220508202548_initial.Designer.cs
@@ -0,0 +1,155 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using OemanTrader.EntityFramework;
+
+#nullable disable
+
+namespace OemanTrader.EntityFramework.Migrations
+{
+ [DbContext(typeof(OemanTraderDbContext))]
+ [Migration("20220508202548_initial")]
+ partial class initial
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "6.0.4")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1);
+
+ modelBuilder.Entity("OemanTrader.Domain.Models.Account", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1);
+
+ b.Property("AccountHolderId")
+ .HasColumnType("int");
+
+ b.Property("Balance")
+ .HasColumnType("float");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AccountHolderId");
+
+ b.ToTable("Accounts");
+ });
+
+ modelBuilder.Entity("OemanTrader.Domain.Models.AssetTransaction", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1);
+
+ b.Property("AccountId")
+ .HasColumnType("int");
+
+ b.Property("DateProcessed")
+ .HasColumnType("datetime2");
+
+ b.Property("IsPurchase")
+ .HasColumnType("bit");
+
+ b.Property("ShareAmount")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AccountId");
+
+ b.ToTable("AssetTransactions");
+ });
+
+ modelBuilder.Entity("OemanTrader.Domain.Models.User", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1);
+
+ b.Property("DateJoined")
+ .HasColumnType("datetime2");
+
+ b.Property("Email")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Password")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("UserName")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("OemanTrader.Domain.Models.Account", b =>
+ {
+ b.HasOne("OemanTrader.Domain.Models.User", "AccountHolder")
+ .WithMany()
+ .HasForeignKey("AccountHolderId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("AccountHolder");
+ });
+
+ modelBuilder.Entity("OemanTrader.Domain.Models.AssetTransaction", b =>
+ {
+ b.HasOne("OemanTrader.Domain.Models.Account", "Account")
+ .WithMany("AssetTransactions")
+ .HasForeignKey("AccountId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.OwnsOne("OemanTrader.Domain.Models.Stock", "Stock", b1 =>
+ {
+ b1.Property("AssetTransactionId")
+ .HasColumnType("int");
+
+ b1.Property("PricePerShare")
+ .HasColumnType("float");
+
+ b1.Property("Symbol")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b1.HasKey("AssetTransactionId");
+
+ b1.ToTable("AssetTransactions");
+
+ b1.WithOwner()
+ .HasForeignKey("AssetTransactionId");
+ });
+
+ b.Navigation("Account");
+
+ b.Navigation("Stock")
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("OemanTrader.Domain.Models.Account", b =>
+ {
+ b.Navigation("AssetTransactions");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/OemanTrader.EntityFramework/Migrations/20220508202548_initial.cs b/OemanTrader.EntityFramework/Migrations/20220508202548_initial.cs
new file mode 100644
index 0000000..417e6b1
--- /dev/null
+++ b/OemanTrader.EntityFramework/Migrations/20220508202548_initial.cs
@@ -0,0 +1,95 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace OemanTrader.EntityFramework.Migrations
+{
+ public partial class initial : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "Users",
+ columns: table => new
+ {
+ Id = table.Column(type: "int", nullable: false)
+ .Annotation("SqlServer:Identity", "1, 1"),
+ Email = table.Column(type: "nvarchar(max)", nullable: false),
+ UserName = table.Column(type: "nvarchar(max)", nullable: false),
+ Password = table.Column(type: "nvarchar(max)", nullable: false),
+ DateJoined = table.Column(type: "datetime2", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Users", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Accounts",
+ columns: table => new
+ {
+ Id = table.Column(type: "int", nullable: false)
+ .Annotation("SqlServer:Identity", "1, 1"),
+ AccountHolderId = table.Column(type: "int", nullable: false),
+ Balance = table.Column(type: "float", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Accounts", x => x.Id);
+ table.ForeignKey(
+ name: "FK_Accounts_Users_AccountHolderId",
+ column: x => x.AccountHolderId,
+ principalTable: "Users",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "AssetTransactions",
+ columns: table => new
+ {
+ Id = table.Column(type: "int", nullable: false)
+ .Annotation("SqlServer:Identity", "1, 1"),
+ AccountId = table.Column(type: "int", nullable: false),
+ IsPurchase = table.Column(type: "bit", nullable: false),
+ Stock_Symbol = table.Column(type: "nvarchar(max)", nullable: false),
+ Stock_PricePerShare = table.Column(type: "float", nullable: false),
+ ShareAmount = table.Column(type: "int", nullable: false),
+ DateProcessed = table.Column(type: "datetime2", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_AssetTransactions", x => x.Id);
+ table.ForeignKey(
+ name: "FK_AssetTransactions_Accounts_AccountId",
+ column: x => x.AccountId,
+ principalTable: "Accounts",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Accounts_AccountHolderId",
+ table: "Accounts",
+ column: "AccountHolderId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_AssetTransactions_AccountId",
+ table: "AssetTransactions",
+ column: "AccountId");
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "AssetTransactions");
+
+ migrationBuilder.DropTable(
+ name: "Accounts");
+
+ migrationBuilder.DropTable(
+ name: "Users");
+ }
+ }
+}
diff --git a/OemanTrader.EntityFramework/Migrations/20220519211347_stock-to-asset.Designer.cs b/OemanTrader.EntityFramework/Migrations/20220519211347_stock-to-asset.Designer.cs
new file mode 100644
index 0000000..a18d08e
--- /dev/null
+++ b/OemanTrader.EntityFramework/Migrations/20220519211347_stock-to-asset.Designer.cs
@@ -0,0 +1,155 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using OemanTrader.EntityFramework;
+
+#nullable disable
+
+namespace OemanTrader.EntityFramework.Migrations
+{
+ [DbContext(typeof(OemanTraderDbContext))]
+ [Migration("20220519211347_stock-to-asset")]
+ partial class stocktoasset
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "6.0.4")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1);
+
+ modelBuilder.Entity("OemanTrader.Domain.Models.Account", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1);
+
+ b.Property("AccountHolderId")
+ .HasColumnType("int");
+
+ b.Property("Balance")
+ .HasColumnType("float");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AccountHolderId");
+
+ b.ToTable("Accounts");
+ });
+
+ modelBuilder.Entity("OemanTrader.Domain.Models.AssetTransaction", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1);
+
+ b.Property("AccountId")
+ .HasColumnType("int");
+
+ b.Property("DateProcessed")
+ .HasColumnType("datetime2");
+
+ b.Property("IsPurchase")
+ .HasColumnType("bit");
+
+ b.Property("ShareAmount")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AccountId");
+
+ b.ToTable("AssetTransactions");
+ });
+
+ modelBuilder.Entity("OemanTrader.Domain.Models.User", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1);
+
+ b.Property("DateJoined")
+ .HasColumnType("datetime2");
+
+ b.Property("Email")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Password")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("UserName")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("OemanTrader.Domain.Models.Account", b =>
+ {
+ b.HasOne("OemanTrader.Domain.Models.User", "AccountHolder")
+ .WithMany()
+ .HasForeignKey("AccountHolderId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("AccountHolder");
+ });
+
+ modelBuilder.Entity("OemanTrader.Domain.Models.AssetTransaction", b =>
+ {
+ b.HasOne("OemanTrader.Domain.Models.Account", "Account")
+ .WithMany("AssetTransactions")
+ .HasForeignKey("AccountId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.OwnsOne("OemanTrader.Domain.Models.Asset", "Asset", b1 =>
+ {
+ b1.Property("AssetTransactionId")
+ .HasColumnType("int");
+
+ b1.Property("PricePerShare")
+ .HasColumnType("float");
+
+ b1.Property("Symbol")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b1.HasKey("AssetTransactionId");
+
+ b1.ToTable("AssetTransactions");
+
+ b1.WithOwner()
+ .HasForeignKey("AssetTransactionId");
+ });
+
+ b.Navigation("Account");
+
+ b.Navigation("Asset")
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("OemanTrader.Domain.Models.Account", b =>
+ {
+ b.Navigation("AssetTransactions");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/OemanTrader.EntityFramework/Migrations/20220519211347_stock-to-asset.cs b/OemanTrader.EntityFramework/Migrations/20220519211347_stock-to-asset.cs
new file mode 100644
index 0000000..2870514
--- /dev/null
+++ b/OemanTrader.EntityFramework/Migrations/20220519211347_stock-to-asset.cs
@@ -0,0 +1,35 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace OemanTrader.EntityFramework.Migrations
+{
+ public partial class stocktoasset : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.RenameColumn(
+ name: "Stock_Symbol",
+ table: "AssetTransactions",
+ newName: "Asset_Symbol");
+
+ migrationBuilder.RenameColumn(
+ name: "Stock_PricePerShare",
+ table: "AssetTransactions",
+ newName: "Asset_PricePerShare");
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.RenameColumn(
+ name: "Asset_Symbol",
+ table: "AssetTransactions",
+ newName: "Stock_Symbol");
+
+ migrationBuilder.RenameColumn(
+ name: "Asset_PricePerShare",
+ table: "AssetTransactions",
+ newName: "Stock_PricePerShare");
+ }
+ }
+}
diff --git a/OemanTrader.EntityFramework/Migrations/OemanTraderDbContextModelSnapshot.cs b/OemanTrader.EntityFramework/Migrations/OemanTraderDbContextModelSnapshot.cs
new file mode 100644
index 0000000..89200b4
--- /dev/null
+++ b/OemanTrader.EntityFramework/Migrations/OemanTraderDbContextModelSnapshot.cs
@@ -0,0 +1,153 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using OemanTrader.EntityFramework;
+
+#nullable disable
+
+namespace OemanTrader.EntityFramework.Migrations
+{
+ [DbContext(typeof(OemanTraderDbContext))]
+ partial class OemanTraderDbContextModelSnapshot : ModelSnapshot
+ {
+ protected override void BuildModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "6.0.4")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1);
+
+ modelBuilder.Entity("OemanTrader.Domain.Models.Account", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1);
+
+ b.Property("AccountHolderId")
+ .HasColumnType("int");
+
+ b.Property("Balance")
+ .HasColumnType("float");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AccountHolderId");
+
+ b.ToTable("Accounts");
+ });
+
+ modelBuilder.Entity("OemanTrader.Domain.Models.AssetTransaction", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1);
+
+ b.Property("AccountId")
+ .HasColumnType("int");
+
+ b.Property("DateProcessed")
+ .HasColumnType("datetime2");
+
+ b.Property("IsPurchase")
+ .HasColumnType("bit");
+
+ b.Property("ShareAmount")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AccountId");
+
+ b.ToTable("AssetTransactions");
+ });
+
+ modelBuilder.Entity("OemanTrader.Domain.Models.User", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1);
+
+ b.Property("DateJoined")
+ .HasColumnType("datetime2");
+
+ b.Property("Email")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Password")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("UserName")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("OemanTrader.Domain.Models.Account", b =>
+ {
+ b.HasOne("OemanTrader.Domain.Models.User", "AccountHolder")
+ .WithMany()
+ .HasForeignKey("AccountHolderId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("AccountHolder");
+ });
+
+ modelBuilder.Entity("OemanTrader.Domain.Models.AssetTransaction", b =>
+ {
+ b.HasOne("OemanTrader.Domain.Models.Account", "Account")
+ .WithMany("AssetTransactions")
+ .HasForeignKey("AccountId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.OwnsOne("OemanTrader.Domain.Models.Asset", "Asset", b1 =>
+ {
+ b1.Property("AssetTransactionId")
+ .HasColumnType("int");
+
+ b1.Property("PricePerShare")
+ .HasColumnType("float");
+
+ b1.Property("Symbol")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b1.HasKey("AssetTransactionId");
+
+ b1.ToTable("AssetTransactions");
+
+ b1.WithOwner()
+ .HasForeignKey("AssetTransactionId");
+ });
+
+ b.Navigation("Account");
+
+ b.Navigation("Asset")
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("OemanTrader.Domain.Models.Account", b =>
+ {
+ b.Navigation("AssetTransactions");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/OemanTrader.EntityFramework/OemanTrader.EntityFramework.csproj b/OemanTrader.EntityFramework/OemanTrader.EntityFramework.csproj
new file mode 100644
index 0000000..f6ce576
--- /dev/null
+++ b/OemanTrader.EntityFramework/OemanTrader.EntityFramework.csproj
@@ -0,0 +1,22 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
diff --git a/OemanTrader.EntityFramework/OemanTraderDbContext.cs b/OemanTrader.EntityFramework/OemanTraderDbContext.cs
new file mode 100644
index 0000000..848b15e
--- /dev/null
+++ b/OemanTrader.EntityFramework/OemanTraderDbContext.cs
@@ -0,0 +1,26 @@
+using Microsoft.EntityFrameworkCore;
+using OemanTrader.Domain.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.EntityFramework
+{
+ public class OemanTraderDbContext : DbContext
+ {
+
+ public DbSet Users { get; set; }
+ public DbSet Accounts { get; set; }
+ public DbSet AssetTransactions { get; set; }
+ public OemanTraderDbContext(DbContextOptions options) : base(options) { }
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ modelBuilder.Entity().OwnsOne(x => x.Asset);
+ base.OnModelCreating(modelBuilder);
+ }
+
+ }
+}
diff --git a/OemanTrader.EntityFramework/OemanTraderDbContextFactory.cs b/OemanTrader.EntityFramework/OemanTraderDbContextFactory.cs
new file mode 100644
index 0000000..bcab666
--- /dev/null
+++ b/OemanTrader.EntityFramework/OemanTraderDbContextFactory.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Design;
+
+namespace OemanTrader.EntityFramework
+{
+ public class OemanTraderDbContextFactory : IDesignTimeDbContextFactory
+ {
+ public OemanTraderDbContext CreateDbContext(string[] args = null)
+ {
+ var options = new DbContextOptionsBuilder();
+ options.UseSqlServer("Server=oemansv7win;Initial Catalog=OemanTraderDB;Persist Security Info=True;User ID=sa;Password=SAOemansv7SA;");
+ return new OemanTraderDbContext(options.Options);
+ }
+ }
+}
diff --git a/OemanTrader.EntityFramework/Services/GenericDataService.cs b/OemanTrader.EntityFramework/Services/GenericDataService.cs
new file mode 100644
index 0000000..7b98e7a
--- /dev/null
+++ b/OemanTrader.EntityFramework/Services/GenericDataService.cs
@@ -0,0 +1,73 @@
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.ChangeTracking;
+using OemanTrader.Domain.Models;
+using OemanTrader.Domain.Services;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.EntityFramework.Services
+{
+ public class GenericDataService : IDataService where T : DomainObject
+ {
+ private readonly OemanTraderDbContextFactory _contextFactory;
+
+ public GenericDataService(OemanTraderDbContextFactory contextFactory)
+ {
+ _contextFactory = contextFactory;
+ }
+
+ public async Task Create(T entity)
+ {
+ using (var context = _contextFactory.CreateDbContext())
+ {
+ EntityEntry createdResult = await context.Set().AddAsync(entity);
+
+ await context.SaveChangesAsync();
+ return createdResult.Entity;
+ }
+ }
+ public async Task Delete(int id)
+ {
+ using (var context = _contextFactory.CreateDbContext())
+ {
+
+ T entity = await context.Set().FirstOrDefaultAsync((e) => e.Id == id);
+ context.Set().Remove(entity);
+ await context.SaveChangesAsync();
+ return true;
+ }
+ }
+
+ public async Task Get(int id)
+ {
+ using (var context = _contextFactory.CreateDbContext())
+ {
+ T entity = await context.Set().FirstOrDefaultAsync((e) => e.Id == id);
+ return entity;
+ }
+ }
+
+ public async Task> GetAll()
+ {
+ using (var context = _contextFactory.CreateDbContext())
+ {
+ IEnumerable entities = await context.Set().ToListAsync();
+ return entities;
+ }
+ }
+
+ public async Task Update(int Id, T entity)
+ {
+ using (var context = _contextFactory.CreateDbContext())
+ {
+ entity.Id = Id;
+ context.Set().Update(entity);
+ await context.SaveChangesAsync();
+ return entity;
+ }
+ }
+ }
+}
diff --git a/OemanTrader.FinantialModelingPrepAPI/FinancialModelingPrepHttpClient.cs b/OemanTrader.FinantialModelingPrepAPI/FinancialModelingPrepHttpClient.cs
new file mode 100644
index 0000000..b38b5b4
--- /dev/null
+++ b/OemanTrader.FinantialModelingPrepAPI/FinancialModelingPrepHttpClient.cs
@@ -0,0 +1,31 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Net.Http;
+
+namespace OemanTrader.FinantialModelingPrepAPI
+{
+ public class FinancialModelingPrepHttpClient : HttpClient
+ {
+ private readonly string _apiKey;
+
+ public FinancialModelingPrepHttpClient(string apiKey)
+ {
+ this.BaseAddress = new Uri("https://financialmodelingprep.com/api/v3/");
+ _apiKey = apiKey;
+ }
+
+ public async Task GetAsync(string uri)
+ {
+ // HttpResponseMessage response = await GetAsync(uri + "?apikey=2035d4934632e1d7c38f15982e39d3aa");
+ //var apikey = "2035d4934632e1d7c38f15982e39d3aa";
+ HttpResponseMessage response = await GetAsync($"{uri}?apikey={_apiKey}");
+ string jsonResponse = await response.Content.ReadAsStringAsync();
+
+ return JsonConvert.DeserializeObject(jsonResponse);
+ }
+ }
+}
diff --git a/OemanTrader.FinantialModelingPrepAPI/FinancialModelingPrepHttpClientFactory.cs b/OemanTrader.FinantialModelingPrepAPI/FinancialModelingPrepHttpClientFactory.cs
new file mode 100644
index 0000000..9c25274
--- /dev/null
+++ b/OemanTrader.FinantialModelingPrepAPI/FinancialModelingPrepHttpClientFactory.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.FinantialModelingPrepAPI
+{
+ public class FinancialModelingPrepHttpClientFactory
+ {
+ private readonly string _apiKey;
+
+ public FinancialModelingPrepHttpClientFactory(string apiKey)
+ {
+ _apiKey = apiKey;
+ }
+
+ public FinancialModelingPrepHttpClient CreateHttpClient()
+ {
+ return new FinancialModelingPrepHttpClient(_apiKey);
+ }
+ }
+}
diff --git a/OemanTrader.FinantialModelingPrepAPI/OemanTrader.FinantialModelingPrepAPI.csproj b/OemanTrader.FinantialModelingPrepAPI/OemanTrader.FinantialModelingPrepAPI.csproj
new file mode 100644
index 0000000..56f998e
--- /dev/null
+++ b/OemanTrader.FinantialModelingPrepAPI/OemanTrader.FinantialModelingPrepAPI.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/OemanTrader.FinantialModelingPrepAPI/Results/StockPriceResult.cs b/OemanTrader.FinantialModelingPrepAPI/Results/StockPriceResult.cs
new file mode 100644
index 0000000..59a0b9d
--- /dev/null
+++ b/OemanTrader.FinantialModelingPrepAPI/Results/StockPriceResult.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.FinantialModelingPrepAPI.Results
+{
+ public class StockPriceResult
+ {
+ public double Price { get; set; }
+ }
+}
diff --git a/OemanTrader.FinantialModelingPrepAPI/Services/MajorIndexService.cs b/OemanTrader.FinantialModelingPrepAPI/Services/MajorIndexService.cs
new file mode 100644
index 0000000..b5c7a25
--- /dev/null
+++ b/OemanTrader.FinantialModelingPrepAPI/Services/MajorIndexService.cs
@@ -0,0 +1,50 @@
+using Newtonsoft.Json;
+using OemanTrader.Domain.Models;
+using OemanTrader.Domain.Services;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.FinantialModelingPrepAPI.Services
+{
+ public class MajorIndexService : IMajorIndexService
+ {
+ private readonly FinancialModelingPrepHttpClientFactory _httpClientFactory;
+
+ public MajorIndexService(FinancialModelingPrepHttpClientFactory httpClientFactory)
+ {
+ _httpClientFactory = httpClientFactory;
+ }
+
+ public async Task GetMajorIndex(MajorIndexType indexType)
+ {
+ using (FinancialModelingPrepHttpClient client = _httpClientFactory.CreateHttpClient())
+ {
+ string uri = "majors-indexes/" + GetUriSuffix(indexType);
+
+ //HttpResponseMessage response = await client.GetAsync(uri + "?apikey=2035d4934632e1d7c38f15982e39d3aa");
+ MajorIndex majorIndex = await client.GetAsync(uri);
+ majorIndex.Type = indexType;
+
+ return majorIndex;
+ }
+ }
+
+ private string GetUriSuffix(MajorIndexType indexType)
+ {
+ switch (indexType)
+ {
+ case MajorIndexType.DowJones:
+ return ".DJI";
+ case MajorIndexType.Nasdaq:
+ return ".IXIC";
+ case MajorIndexType.SP500:
+ return ".INX";
+ default:
+ throw new Exception("MajorIndexType does not have a suffix defined.");
+ }
+ }
+ }
+}
diff --git a/OemanTrader.FinantialModelingPrepAPI/Services/StockPriceService.cs b/OemanTrader.FinantialModelingPrepAPI/Services/StockPriceService.cs
new file mode 100644
index 0000000..f829b50
--- /dev/null
+++ b/OemanTrader.FinantialModelingPrepAPI/Services/StockPriceService.cs
@@ -0,0 +1,38 @@
+using OemanTrader.Domain.Exceptions;
+using OemanTrader.Domain.Services;
+using OemanTrader.FinantialModelingPrepAPI.Results;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.FinantialModelingPrepAPI.Services
+{
+ public class StockPriceService : IStockPriceService
+ {
+ private readonly FinancialModelingPrepHttpClientFactory _httpClientFactory;
+
+ public StockPriceService(FinancialModelingPrepHttpClientFactory httpClientFactory)
+ {
+ _httpClientFactory = httpClientFactory;
+ }
+ public async Task GetPrice(string symbol)
+ {
+ using (FinancialModelingPrepHttpClient client = _httpClientFactory.CreateHttpClient())
+ {
+ string uri = "stock/real-time-price/" + symbol;
+
+ //HttpResponseMessage response = await client.GetAsync(uri + "?apikey=2035d4934632e1d7c38f15982e39d3aa");
+ StockPriceResult stockPriceResult = await client.GetAsync(uri);
+
+ if (stockPriceResult.Price == 0)
+ {
+ throw new InvalidSymbolException(symbol);
+ }
+
+ return stockPriceResult.Price;
+ }
+ }
+ }
+}
diff --git a/OemanTrader.WPF/App.xaml b/OemanTrader.WPF/App.xaml
new file mode 100644
index 0000000..4673a5b
--- /dev/null
+++ b/OemanTrader.WPF/App.xaml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/OemanTrader.WPF/App.xaml.cs b/OemanTrader.WPF/App.xaml.cs
new file mode 100644
index 0000000..121c8f8
--- /dev/null
+++ b/OemanTrader.WPF/App.xaml.cs
@@ -0,0 +1,44 @@
+using Microsoft.Extensions.DependencyInjection;
+using OemanTrader.FinantialModelingPrepAPI.Services;
+using OemanTrader.WPF.ViewModels;
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace OemanTrader.WPF
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ protected override void OnStartup(StartupEventArgs e)
+ {
+ //new MajorIndexService().GetMajorIndex(Domain.Models.MajorIndexType.DowJones).ContinueWith((t) =>
+ //{
+ // var index = t.Result;
+ //});
+
+ Window window = new MainWindow();
+ window.DataContext = new MainViewModel();
+ window.Show();
+
+ base.OnStartup(e);
+ }
+
+ private IServiceProvider CreateServiceProvider()
+ {
+ // 1. Singelton - one instance per application
+ // 2. Transient - different instance everytime
+ // 3. Scoped - one instance per "scope"
+
+ IServiceCollection services = new ServiceCollection();
+ return services.BuildServiceProvider();
+
+ }
+ }
+}
diff --git a/OemanTrader.WPF/AssemblyInfo.cs b/OemanTrader.WPF/AssemblyInfo.cs
new file mode 100644
index 0000000..8b5504e
--- /dev/null
+++ b/OemanTrader.WPF/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Windows;
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
diff --git a/OemanTrader.WPF/Commands/UpdateCurrentViewModelCommand.cs b/OemanTrader.WPF/Commands/UpdateCurrentViewModelCommand.cs
new file mode 100644
index 0000000..e260ab6
--- /dev/null
+++ b/OemanTrader.WPF/Commands/UpdateCurrentViewModelCommand.cs
@@ -0,0 +1,48 @@
+using OemanTrader.FinantialModelingPrepAPI.Services;
+using OemanTrader.WPF.State.Navigators;
+using OemanTrader.WPF.ViewModels;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Input;
+
+namespace OemanTrader.WPF.Commands
+{
+ public class UpdateCurrentViewModelCommand : ICommand
+ {
+ public event EventHandler? CanExecuteChanged;
+ private INavigator _navigator;
+
+ public UpdateCurrentViewModelCommand(INavigator navigator)
+ {
+ _navigator = navigator;
+ }
+
+ public bool CanExecute(object? parameter)
+ {
+ return true;
+ }
+
+ public void Execute(object? parameter)
+ {
+ if (parameter is ViewType)
+ {
+ ViewType viewType = (ViewType)parameter;
+ switch (viewType)
+ {
+ case ViewType.Home:
+ // OBS OBS
+ //_navigator.CurrentViewModel = new HomeViewModel(MajorIndexViewModel.LoadMajorIndexViewModel(new MajorIndexService()));
+ break;
+ case ViewType.Portfolio:
+ _navigator.CurrentViewModel = new PortfolioViewModel();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
diff --git a/OemanTrader.WPF/Controls/MajorIndexCard.xaml b/OemanTrader.WPF/Controls/MajorIndexCard.xaml
new file mode 100644
index 0000000..0028427
--- /dev/null
+++ b/OemanTrader.WPF/Controls/MajorIndexCard.xaml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/OemanTrader.WPF/Controls/MajorIndexCard.xaml.cs b/OemanTrader.WPF/Controls/MajorIndexCard.xaml.cs
new file mode 100644
index 0000000..3699dd1
--- /dev/null
+++ b/OemanTrader.WPF/Controls/MajorIndexCard.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace OemanTrader.WPF.Controls
+{
+ ///
+ /// Interaction logic for MajorIndexCard.xaml
+ ///
+ public partial class MajorIndexCard : UserControl
+ {
+ public MajorIndexCard()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/OemanTrader.WPF/Controls/MajorIndexListing.xaml b/OemanTrader.WPF/Controls/MajorIndexListing.xaml
new file mode 100644
index 0000000..8fd58cc
--- /dev/null
+++ b/OemanTrader.WPF/Controls/MajorIndexListing.xaml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/OemanTrader.WPF/Controls/MajorIndexListing.xaml.cs b/OemanTrader.WPF/Controls/MajorIndexListing.xaml.cs
new file mode 100644
index 0000000..7f016f5
--- /dev/null
+++ b/OemanTrader.WPF/Controls/MajorIndexListing.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace OemanTrader.WPF.Controls
+{
+ ///
+ /// Interaction logic for MajorIndexListing.xaml
+ ///
+ public partial class MajorIndexListing : UserControl
+ {
+ public MajorIndexListing()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/OemanTrader.WPF/Controls/NavigationBar.xaml b/OemanTrader.WPF/Controls/NavigationBar.xaml
new file mode 100644
index 0000000..eb2e71c
--- /dev/null
+++ b/OemanTrader.WPF/Controls/NavigationBar.xaml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/OemanTrader.WPF/Controls/NavigationBar.xaml.cs b/OemanTrader.WPF/Controls/NavigationBar.xaml.cs
new file mode 100644
index 0000000..e47bb2b
--- /dev/null
+++ b/OemanTrader.WPF/Controls/NavigationBar.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace OemanTrader.WPF.Controls
+{
+ ///
+ /// Interaction logic for NavigationBar.xaml
+ ///
+ public partial class NavigationBar : UserControl
+ {
+ public NavigationBar()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/OemanTrader.WPF/Converters/EqualValueToParameterConverter.cs b/OemanTrader.WPF/Converters/EqualValueToParameterConverter.cs
new file mode 100644
index 0000000..1578dc7
--- /dev/null
+++ b/OemanTrader.WPF/Converters/EqualValueToParameterConverter.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+
+namespace OemanTrader.WPF.Converters
+{
+ public class EqualValueToParameterConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ string valueString = value.ToString();
+ string parameterString = parameter.ToString();
+
+ return value.ToString() == parameter.ToString();
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/OemanTrader.WPF/MainWindow.xaml b/OemanTrader.WPF/MainWindow.xaml
new file mode 100644
index 0000000..44611d2
--- /dev/null
+++ b/OemanTrader.WPF/MainWindow.xaml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/OemanTrader.WPF/MainWindow.xaml.cs b/OemanTrader.WPF/MainWindow.xaml.cs
new file mode 100644
index 0000000..2d93caf
--- /dev/null
+++ b/OemanTrader.WPF/MainWindow.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace OemanTrader.WPF
+{
+ ///
+ /// Interaction logic for MainWindow.xaml
+ ///
+ public partial class MainWindow : Window
+ {
+ public MainWindow()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/OemanTrader.WPF/Models/ObservableObject.cs b/OemanTrader.WPF/Models/ObservableObject.cs
new file mode 100644
index 0000000..1f9a501
--- /dev/null
+++ b/OemanTrader.WPF/Models/ObservableObject.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.WPF.Models
+{
+ public class ObservableObject : INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler? PropertyChanged;
+ protected void OnPropertyChanged(string propertyName)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+}
diff --git a/OemanTrader.WPF/OemanTrader.WPF.csproj b/OemanTrader.WPF/OemanTrader.WPF.csproj
new file mode 100644
index 0000000..3174503
--- /dev/null
+++ b/OemanTrader.WPF/OemanTrader.WPF.csproj
@@ -0,0 +1,16 @@
+
+
+
+ WinExe
+ net6.0-windows
+ enable
+ true
+
+
+
+
+
+
+
+
+
diff --git a/OemanTrader.WPF/State/Navigators/INavigator.cs b/OemanTrader.WPF/State/Navigators/INavigator.cs
new file mode 100644
index 0000000..2031755
--- /dev/null
+++ b/OemanTrader.WPF/State/Navigators/INavigator.cs
@@ -0,0 +1,21 @@
+using OemanTrader.WPF.ViewModels;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Input;
+
+namespace OemanTrader.WPF.State.Navigators
+{
+ public enum ViewType
+ {
+ Home,
+ Portfolio
+ }
+ public interface INavigator
+ {
+ ViewModelBase CurrentViewModel { get; set; }
+ ICommand UpdateCurrentViewModelCommand { get; }
+ }
+}
diff --git a/OemanTrader.WPF/State/Navigators/Navigator.cs b/OemanTrader.WPF/State/Navigators/Navigator.cs
new file mode 100644
index 0000000..3e5ecd4
--- /dev/null
+++ b/OemanTrader.WPF/State/Navigators/Navigator.cs
@@ -0,0 +1,34 @@
+using OemanTrader.WPF.Commands;
+using OemanTrader.WPF.Models;
+using OemanTrader.WPF.ViewModels;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Input;
+
+namespace OemanTrader.WPF.State.Navigators
+{
+ public class Navigator : ObservableObject, INavigator
+ {
+ private ViewModelBase _currentViewModel;
+ public ViewModelBase CurrentViewModel
+ {
+ get
+ {
+ return _currentViewModel;
+ }
+
+ set
+ {
+ _currentViewModel = value;
+ OnPropertyChanged(nameof(CurrentViewModel));
+ }
+ }
+ public ICommand UpdateCurrentViewModelCommand => new UpdateCurrentViewModelCommand(this);
+
+
+ }
+}
diff --git a/OemanTrader.WPF/Styles/Common.xaml b/OemanTrader.WPF/Styles/Common.xaml
new file mode 100644
index 0000000..53e1d63
--- /dev/null
+++ b/OemanTrader.WPF/Styles/Common.xaml
@@ -0,0 +1,10 @@
+
+
+ #799540
+ #50632b
+
+
+
+
+
\ No newline at end of file
diff --git a/OemanTrader.WPF/Styles/NavigationBar.xaml b/OemanTrader.WPF/Styles/NavigationBar.xaml
new file mode 100644
index 0000000..ff164a5
--- /dev/null
+++ b/OemanTrader.WPF/Styles/NavigationBar.xaml
@@ -0,0 +1,43 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/OemanTrader.WPF/ViewModels/HomeViewModel.cs b/OemanTrader.WPF/ViewModels/HomeViewModel.cs
new file mode 100644
index 0000000..b2c5c94
--- /dev/null
+++ b/OemanTrader.WPF/ViewModels/HomeViewModel.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.WPF.ViewModels
+{
+ public class HomeViewModel : ViewModelBase
+ {
+ public MajorIndexListingViewModel MajorIndexListingViewModel { get; set; }
+
+ public HomeViewModel(MajorIndexListingViewModel majorIndexListingViewModel)
+ {
+ MajorIndexListingViewModel = majorIndexListingViewModel;
+ }
+ }
+}
diff --git a/OemanTrader.WPF/ViewModels/MainViewModel.cs b/OemanTrader.WPF/ViewModels/MainViewModel.cs
new file mode 100644
index 0000000..359621f
--- /dev/null
+++ b/OemanTrader.WPF/ViewModels/MainViewModel.cs
@@ -0,0 +1,19 @@
+using OemanTrader.WPF.State.Navigators;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.WPF.ViewModels
+{
+ public class MainViewModel : ViewModelBase
+ {
+ public INavigator Navigator { get; set; } = new Navigator();
+
+ public MainViewModel()
+ {
+ Navigator.UpdateCurrentViewModelCommand.Execute(ViewType.Home);
+ }
+ }
+}
diff --git a/OemanTrader.WPF/ViewModels/MajorIndexListingViewModel.cs b/OemanTrader.WPF/ViewModels/MajorIndexListingViewModel.cs
new file mode 100644
index 0000000..fb3343b
--- /dev/null
+++ b/OemanTrader.WPF/ViewModels/MajorIndexListingViewModel.cs
@@ -0,0 +1,84 @@
+using OemanTrader.Domain.Models;
+using OemanTrader.Domain.Services;
+using OemanTrader.FinantialModelingPrepAPI.Services;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.WPF.ViewModels
+{
+ public class MajorIndexListingViewModel : ViewModelBase
+ {
+ private readonly IMajorIndexService _majorIndexService;
+
+
+ private MajorIndex _dowJones;
+ public MajorIndex DowJones {
+ get { return _dowJones; }
+ set {
+ _dowJones = value;
+ OnPropertyChanged(nameof(DowJones));
+ }
+ }
+
+ private MajorIndex _nasdaq;
+ public MajorIndex Nasdaq
+ {
+ get { return _nasdaq; }
+ set
+ {
+ _nasdaq = value;
+ OnPropertyChanged(nameof(Nasdaq));
+ }
+ }
+
+ private MajorIndex _sp500;
+ public MajorIndex SP500
+ {
+ get { return _sp500; }
+ set
+ {
+ _sp500 = value;
+ OnPropertyChanged(nameof(SP500));
+ }
+ }
+
+ public MajorIndexListingViewModel(IMajorIndexService majorIndexService)
+ {
+ _majorIndexService = majorIndexService;
+ }
+
+ public static MajorIndexListingViewModel LoadMajorIndexViewModel(IMajorIndexService majorIndexService)
+ {
+ MajorIndexListingViewModel majorIndexViewModel = new MajorIndexListingViewModel(majorIndexService);
+ majorIndexViewModel.LoadMajorIndexes();
+ return majorIndexViewModel;
+ }
+
+ private void LoadMajorIndexes()
+ {
+ _majorIndexService.GetMajorIndex(MajorIndexType.DowJones).ContinueWith(task =>
+ {
+ if(task.Exception == null) {
+ DowJones = task.Result;
+ }
+ });
+ _majorIndexService.GetMajorIndex(MajorIndexType.Nasdaq).ContinueWith(task =>
+ {
+ if (task.Exception == null)
+ {
+ Nasdaq = task.Result;
+ }
+ });
+ _majorIndexService.GetMajorIndex(MajorIndexType.SP500).ContinueWith(task =>
+ {
+ if (task.Exception == null)
+ {
+ SP500 = task.Result;
+ }
+ });
+ }
+ }
+}
diff --git a/OemanTrader.WPF/ViewModels/PortfolioViewModel.cs b/OemanTrader.WPF/ViewModels/PortfolioViewModel.cs
new file mode 100644
index 0000000..5f705bd
--- /dev/null
+++ b/OemanTrader.WPF/ViewModels/PortfolioViewModel.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.WPF.ViewModels
+{
+ public class PortfolioViewModel : ViewModelBase
+ {
+
+ }
+}
diff --git a/OemanTrader.WPF/ViewModels/ViewModelBase.cs b/OemanTrader.WPF/ViewModels/ViewModelBase.cs
new file mode 100644
index 0000000..22b4e33
--- /dev/null
+++ b/OemanTrader.WPF/ViewModels/ViewModelBase.cs
@@ -0,0 +1,13 @@
+using OemanTrader.WPF.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OemanTrader.WPF.ViewModels
+{
+ public class ViewModelBase : ObservableObject
+ {
+ }
+}
diff --git a/OemanTrader.WPF/Views/HomeView.xaml b/OemanTrader.WPF/Views/HomeView.xaml
new file mode 100644
index 0000000..9387aa5
--- /dev/null
+++ b/OemanTrader.WPF/Views/HomeView.xaml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/OemanTrader.WPF/Views/HomeView.xaml.cs b/OemanTrader.WPF/Views/HomeView.xaml.cs
new file mode 100644
index 0000000..ae9f39d
--- /dev/null
+++ b/OemanTrader.WPF/Views/HomeView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace OemanTrader.WPF.Views
+{
+ ///
+ /// Interaction logic for HomeView.xaml
+ ///
+ public partial class HomeView : UserControl
+ {
+ public HomeView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/OemanTrader.WPF/Views/PortfolioView.xaml b/OemanTrader.WPF/Views/PortfolioView.xaml
new file mode 100644
index 0000000..cea150f
--- /dev/null
+++ b/OemanTrader.WPF/Views/PortfolioView.xaml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/OemanTrader.WPF/Views/PortfolioView.xaml.cs b/OemanTrader.WPF/Views/PortfolioView.xaml.cs
new file mode 100644
index 0000000..984f67d
--- /dev/null
+++ b/OemanTrader.WPF/Views/PortfolioView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace OemanTrader.WPF.Views
+{
+ ///
+ /// Interaction logic for PortfolioView.xaml
+ ///
+ public partial class PortfolioView : UserControl
+ {
+ public PortfolioView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/OemanTrader.sln b/OemanTrader.sln
new file mode 100644
index 0000000..d8ae6fb
--- /dev/null
+++ b/OemanTrader.sln
@@ -0,0 +1,43 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.1.32421.90
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OemanTrader.Domain", "OemanTrader.Domain\OemanTrader.Domain.csproj", "{22283C0E-61FB-4012-82C8-A6099D52218B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OemanTrader.EntityFramework", "OemanTrader.EntityFramework\OemanTrader.EntityFramework.csproj", "{961E1C1B-FA81-409A-9D83-3C142E58EA3E}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OemanTrader.WPF", "OemanTrader.WPF\OemanTrader.WPF.csproj", "{AD3FBE7D-8D92-4D5D-97A8-33CDE02C3A32}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OemanTrader.FinantialModelingPrepAPI", "OemanTrader.FinantialModelingPrepAPI\OemanTrader.FinantialModelingPrepAPI.csproj", "{27A084A0-9AF3-4179-AB73-29A7CC723F0C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {22283C0E-61FB-4012-82C8-A6099D52218B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {22283C0E-61FB-4012-82C8-A6099D52218B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {22283C0E-61FB-4012-82C8-A6099D52218B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {22283C0E-61FB-4012-82C8-A6099D52218B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {961E1C1B-FA81-409A-9D83-3C142E58EA3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {961E1C1B-FA81-409A-9D83-3C142E58EA3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {961E1C1B-FA81-409A-9D83-3C142E58EA3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {961E1C1B-FA81-409A-9D83-3C142E58EA3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AD3FBE7D-8D92-4D5D-97A8-33CDE02C3A32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AD3FBE7D-8D92-4D5D-97A8-33CDE02C3A32}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AD3FBE7D-8D92-4D5D-97A8-33CDE02C3A32}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AD3FBE7D-8D92-4D5D-97A8-33CDE02C3A32}.Release|Any CPU.Build.0 = Release|Any CPU
+ {27A084A0-9AF3-4179-AB73-29A7CC723F0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {27A084A0-9AF3-4179-AB73-29A7CC723F0C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {27A084A0-9AF3-4179-AB73-29A7CC723F0C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {27A084A0-9AF3-4179-AB73-29A7CC723F0C}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {F83485AD-4BA3-4B1C-A53B-F835E0221573}
+ EndGlobalSection
+EndGlobal