Oviya commited on
Commit
07cf142
·
1 Parent(s): dd4142a

Serve app via redirect to dist/Pytrade/browser

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .editorconfig +17 -0
  2. CHANGELOG.md +16 -0
  3. Pytrade.esproj +10 -0
  4. Pytrade.sln +27 -0
  5. angular.json +110 -0
  6. index.html +7 -16
  7. karma.conf.js +44 -0
  8. obj/Debug/package.g.props +49 -0
  9. package-lock.json +0 -0
  10. package.json +54 -0
  11. public/44965755.jpg +3 -0
  12. public/bgimg.png +3 -0
  13. public/bgkey-opacity.png +3 -0
  14. public/bgkey.png +3 -0
  15. public/bgvideo.mp4 +3 -0
  16. public/chatbot.png +3 -0
  17. public/desktop_img.png +3 -0
  18. public/favicon.ico +3 -0
  19. public/featureimg.jpg +3 -0
  20. public/filter-img.png +3 -0
  21. public/final.png +3 -0
  22. public/logo.png +3 -0
  23. public/marketselect.jpg +3 -0
  24. public/marketselect.mp4 +3 -0
  25. public/yfinance.png +3 -0
  26. src/app/analysispage/analysispage.html +291 -0
  27. src/app/analysispage/analysispage.scss +156 -0
  28. src/app/analysispage/analysispage.spec.ts +23 -0
  29. src/app/analysispage/analysispage.ts +226 -0
  30. src/app/analysispage/chart.service.ts +558 -0
  31. src/app/app-module.ts +49 -0
  32. src/app/app-routing-module.ts +28 -0
  33. src/app/app.html +19 -0
  34. src/app/app.scss +52 -0
  35. src/app/app.spec.ts +29 -0
  36. src/app/app.ts +11 -0
  37. src/app/chatbot/chatbot.html +10 -0
  38. src/app/chatbot/chatbot.scss +133 -0
  39. src/app/chatbot/chatbot.spec.ts +23 -0
  40. src/app/chatbot/chatbot.ts +49 -0
  41. src/app/homepage/homepage.html +149 -0
  42. src/app/homepage/homepage.scss +217 -0
  43. src/app/homepage/homepage.spec.ts +23 -0
  44. src/app/homepage/homepage.ts +34 -0
  45. src/app/marketselect/market.service.ts +24 -0
  46. src/app/marketselect/marketselect.html +78 -0
  47. src/app/marketselect/marketselect.scss +201 -0
  48. src/app/marketselect/marketselect.spec.ts +23 -0
  49. src/app/marketselect/marketselect.ts +173 -0
  50. src/app/screenerpage/screenerpage.css +83 -0
.editorconfig ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Editor configuration, see https://editorconfig.org
2
+ root = true
3
+
4
+ [*]
5
+ charset = utf-8
6
+ indent_style = space
7
+ indent_size = 2
8
+ insert_final_newline = true
9
+ trim_trailing_whitespace = true
10
+
11
+ [*.ts]
12
+ quote_type = single
13
+ ij_typescript_use_double_quotes = false
14
+
15
+ [*.md]
16
+ max_line_length = off
17
+ trim_trailing_whitespace = false
CHANGELOG.md ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ This file explains how Visual Studio created the project.
2
+
3
+ The following tools were used to generate this project:
4
+ - Angular CLI (ng)
5
+
6
+ The following steps were used to generate this project:
7
+ - Create Angular project with ng: `ng new Pytrade --defaults --skip-install --skip-git --no-standalone `.
8
+ - Update angular.json with port.
9
+ - Create project file (`Pytrade.esproj`).
10
+ - Create `launch.json` to enable debugging.
11
+ - Update package.json to add `jest-editor-support`.
12
+ - Update `start` script in `package.json` to specify host.
13
+ - Add `karma.conf.js` for unit tests.
14
+ - Update `angular.json` to point to `karma.conf.js`.
15
+ - Add project to solution.
16
+ - Write this file.
Pytrade.esproj ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <Project Sdk="Microsoft.VisualStudio.JavaScript.Sdk/1.0.2752196">
2
+ <PropertyGroup>
3
+ <StartupCommand>npm start</StartupCommand>
4
+ <JavaScriptTestFramework>Jasmine</JavaScriptTestFramework>
5
+ <!-- Allows the build (or compile) script located on package.json to run on Build -->
6
+ <ShouldRunBuildScript>false</ShouldRunBuildScript>
7
+ <!-- Folder where production build objects will be placed -->
8
+ <BuildOutputFolder>$(MSBuildProjectDirectory)\dist\Pytrade\browser\</BuildOutputFolder>
9
+ </PropertyGroup>
10
+ </Project>
Pytrade.sln ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 
2
+ Microsoft Visual Studio Solution File, Format Version 12.00
3
+ # Visual Studio Version 17
4
+ VisualStudioVersion = 17.14.36301.6 d17.14
5
+ MinimumVisualStudioVersion = 10.0.40219.1
6
+ Project("{54A90642-561A-4BB1-A94E-469ADEE60C69}") = "Pytrade", "Pytrade.esproj", "{54209CD0-4BE7-905C-7951-7A10E456A6D9}"
7
+ EndProject
8
+ Global
9
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
10
+ Debug|Any CPU = Debug|Any CPU
11
+ Release|Any CPU = Release|Any CPU
12
+ EndGlobalSection
13
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
14
+ {54209CD0-4BE7-905C-7951-7A10E456A6D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15
+ {54209CD0-4BE7-905C-7951-7A10E456A6D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
16
+ {54209CD0-4BE7-905C-7951-7A10E456A6D9}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
17
+ {54209CD0-4BE7-905C-7951-7A10E456A6D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
18
+ {54209CD0-4BE7-905C-7951-7A10E456A6D9}.Release|Any CPU.Build.0 = Release|Any CPU
19
+ {54209CD0-4BE7-905C-7951-7A10E456A6D9}.Release|Any CPU.Deploy.0 = Release|Any CPU
20
+ EndGlobalSection
21
+ GlobalSection(SolutionProperties) = preSolution
22
+ HideSolutionNode = FALSE
23
+ EndGlobalSection
24
+ GlobalSection(ExtensibilityGlobals) = postSolution
25
+ SolutionGuid = {9D215C41-589A-46E9-ABAA-BB49FAEA1A1F}
26
+ EndGlobalSection
27
+ EndGlobal
angular.json ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3
+ "version": 1,
4
+ "newProjectRoot": "projects",
5
+ "projects": {
6
+ "Pytrade": {
7
+ "projectType": "application",
8
+ "schematics": {
9
+ "@schematics/angular:component": {
10
+ "standalone": false
11
+ },
12
+ "@schematics/angular:directive": {
13
+ "standalone": false
14
+ },
15
+ "@schematics/angular:pipe": {
16
+ "standalone": false
17
+ }
18
+ },
19
+ "root": "",
20
+ "sourceRoot": "src",
21
+ "prefix": "app",
22
+ "architect": {
23
+ "build": {
24
+ "builder": "@angular/build:application",
25
+ "options": {
26
+ "browser": "src/main.ts",
27
+ "polyfills": [
28
+ "zone.js"
29
+ ],
30
+ "tsConfig": "tsconfig.app.json",
31
+ "assets": [
32
+ {
33
+ "glob": "**/*",
34
+ "input": "public"
35
+ }
36
+ ],
37
+ "styles": [
38
+ "src/custom-theme.scss",
39
+ "src/styles.css"
40
+ ]
41
+ },
42
+ "configurations": {
43
+ "production": {
44
+ "budgets": [
45
+ {
46
+ "type": "initial",
47
+ "maximumWarning": "500kB",
48
+ "maximumError": "1MB"
49
+ },
50
+ {
51
+ "type": "anyComponentStyle",
52
+ "maximumWarning": "4kB",
53
+ "maximumError": "8kB"
54
+ }
55
+ ],
56
+ "outputHashing": "all"
57
+ },
58
+ "development": {
59
+ "optimization": false,
60
+ "extractLicenses": false,
61
+ "sourceMap": true
62
+ }
63
+ },
64
+ "defaultConfiguration": "production"
65
+ },
66
+ "serve": {
67
+ "builder": "@angular/build:dev-server",
68
+ "configurations": {
69
+ "production": {
70
+ "buildTarget": "Pytrade:build:production"
71
+ },
72
+ "development": {
73
+ "buildTarget": "Pytrade:build:development"
74
+ }
75
+ },
76
+ "defaultConfiguration": "development",
77
+ "options": {
78
+ "port": 57205
79
+ }
80
+ },
81
+ "extract-i18n": {
82
+ "builder": "@angular/build:extract-i18n"
83
+ },
84
+ "test": {
85
+ "builder": "@angular/build:karma",
86
+ "options": {
87
+ "polyfills": [
88
+ "zone.js",
89
+ "zone.js/testing"
90
+ ],
91
+ "tsConfig": "tsconfig.spec.json",
92
+ "assets": [
93
+ {
94
+ "glob": "**/*",
95
+ "input": "public"
96
+ }
97
+ ],
98
+ "styles": [
99
+ "src/styles.css"
100
+ ],
101
+ "karmaConfig": "karma.conf.js"
102
+ }
103
+ }
104
+ }
105
+ }
106
+ },
107
+ "cli": {
108
+ "analytics": "eab27a52-ee79-4cb0-aa82-d323da3c6b06"
109
+ }
110
+ }
index.html CHANGED
@@ -1,19 +1,10 @@
1
  <!doctype html>
2
  <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
  </html>
 
1
  <!doctype html>
2
  <html>
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>Pytrade</title>
6
+ <meta http-equiv="refresh" content="0; url=./dist/Pytrade/browser/">
7
+ <script>window.location.replace('./dist/Pytrade/browser/');</script>
8
+ </head>
9
+ <body></body>
 
 
 
 
 
 
 
 
 
10
  </html>
karma.conf.js ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ module.exports = function (config) {
2
+ config.set({
3
+ basePath: '',
4
+ frameworks: ['jasmine', '@angular-devkit/build-angular'],
5
+ plugins: [
6
+ require('karma-jasmine'),
7
+ require('karma-chrome-launcher'),
8
+ require('karma-jasmine-html-reporter'),
9
+ require('karma-coverage'),
10
+ require('@angular-devkit/build-angular/plugins/karma')
11
+ ],
12
+ client: {
13
+ jasmine: {
14
+ // you can add configuration options for Jasmine here
15
+ // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
16
+ // for example, you can disable the random execution with `random: false`
17
+ // or set a specific seed with `seed: 4321`
18
+ },
19
+ clearContext: false // leave Jasmine Spec Runner output visible in browser
20
+ },
21
+ jasmineHtmlReporter: {
22
+ suppressAll: true // removes the duplicated traces
23
+ },
24
+ coverageReporter: {
25
+ dir: require('path').join(__dirname, './coverage/'),
26
+ subdir: '.',
27
+ reporters: [
28
+ { type: 'html' },
29
+ { type: 'text-summary' }
30
+ ]
31
+ },
32
+ reporters: ['progress', 'kjhtml'],
33
+ port: 9876,
34
+ colors: true,
35
+ logLevel: config.LOG_INFO,
36
+ autoWatch: true,
37
+ browsers: ['Chrome'],
38
+ singleRun: false,
39
+ restartOnFileChange: true,
40
+ listenAddress: 'localhost',
41
+ hostname: 'localhost'
42
+ });
43
+ };
44
+
obj/Debug/package.g.props ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <Project>
3
+ <PropertyGroup>
4
+ <PackageJsonName Condition="$(PackageJsonName) == ''">pytrade</PackageJsonName>
5
+ <PackageJsonVersion Condition="$(PackageJsonVersion) == ''">0.0.0</PackageJsonVersion>
6
+ <PackageJsonScriptsNg Condition="$(PackageJsonScriptsNg) == ''">ng</PackageJsonScriptsNg>
7
+ <PackageJsonScriptsStart Condition="$(PackageJsonScriptsStart) == ''">ng serve --host=127.0.0.1</PackageJsonScriptsStart>
8
+ <PackageJsonScriptsBuild Condition="$(PackageJsonScriptsBuild) == ''">ng build</PackageJsonScriptsBuild>
9
+ <PackageJsonScriptsWatch Condition="$(PackageJsonScriptsWatch) == ''">ng build --watch --configuration development</PackageJsonScriptsWatch>
10
+ <PackageJsonScriptsTest Condition="$(PackageJsonScriptsTest) == ''">ng test</PackageJsonScriptsTest>
11
+ <PackageJsonPrettierPrintwidth Condition="$(PackageJsonPrettierPrintwidth) == ''">100</PackageJsonPrettierPrintwidth>
12
+ <PackageJsonPrettierSinglequote Condition="$(PackageJsonPrettierSinglequote) == ''">true</PackageJsonPrettierSinglequote>
13
+ <PackageJsonPrettierOverrides Condition="$(PackageJsonPrettierOverrides) == ''">[
14
+ {
15
+ "files": "*.html",
16
+ "options": {
17
+ "parser": "angular"
18
+ }
19
+ }
20
+ ]</PackageJsonPrettierOverrides>
21
+ <PackageJsonPrivate Condition="$(PackageJsonPrivate) == ''">true</PackageJsonPrivate>
22
+ <PackageJsonDependenciesAngularCdk Condition="$(PackageJsonDependenciesAngularCdk) == ''">^20.2.1</PackageJsonDependenciesAngularCdk>
23
+ <PackageJsonDependenciesAngularCommon Condition="$(PackageJsonDependenciesAngularCommon) == ''">^20.2.0</PackageJsonDependenciesAngularCommon>
24
+ <PackageJsonDependenciesAngularCompiler Condition="$(PackageJsonDependenciesAngularCompiler) == ''">^20.2.0</PackageJsonDependenciesAngularCompiler>
25
+ <PackageJsonDependenciesAngularCore Condition="$(PackageJsonDependenciesAngularCore) == ''">^20.2.0</PackageJsonDependenciesAngularCore>
26
+ <PackageJsonDependenciesAngularForms Condition="$(PackageJsonDependenciesAngularForms) == ''">^20.2.0</PackageJsonDependenciesAngularForms>
27
+ <PackageJsonDependenciesAngularMaterial Condition="$(PackageJsonDependenciesAngularMaterial) == ''">^20.2.1</PackageJsonDependenciesAngularMaterial>
28
+ <PackageJsonDependenciesAngularPlatformBrowser Condition="$(PackageJsonDependenciesAngularPlatformBrowser) == ''">^20.2.0</PackageJsonDependenciesAngularPlatformBrowser>
29
+ <PackageJsonDependenciesAngularRouter Condition="$(PackageJsonDependenciesAngularRouter) == ''">^20.2.0</PackageJsonDependenciesAngularRouter>
30
+ <PackageJsonDependenciesApexcharts Condition="$(PackageJsonDependenciesApexcharts) == ''">^5.3.4</PackageJsonDependenciesApexcharts>
31
+ <PackageJsonDependenciesAxios Condition="$(PackageJsonDependenciesAxios) == ''">^1.11.0</PackageJsonDependenciesAxios>
32
+ <PackageJsonDependenciesJestEditorSupport Condition="$(PackageJsonDependenciesJestEditorSupport) == ''">*</PackageJsonDependenciesJestEditorSupport>
33
+ <PackageJsonDependenciesNgApexcharts Condition="$(PackageJsonDependenciesNgApexcharts) == ''">^2.0.1</PackageJsonDependenciesNgApexcharts>
34
+ <PackageJsonDependenciesRxjs Condition="$(PackageJsonDependenciesRxjs) == ''">~7.8.0</PackageJsonDependenciesRxjs>
35
+ <PackageJsonDependenciesTslib Condition="$(PackageJsonDependenciesTslib) == ''">^2.3.0</PackageJsonDependenciesTslib>
36
+ <PackageJsonDependenciesZoneJs Condition="$(PackageJsonDependenciesZoneJs) == ''">~0.15.0</PackageJsonDependenciesZoneJs>
37
+ <PackageJsonDevdependenciesAngularBuild Condition="$(PackageJsonDevdependenciesAngularBuild) == ''">^20.2.0</PackageJsonDevdependenciesAngularBuild>
38
+ <PackageJsonDevdependenciesAngularCli Condition="$(PackageJsonDevdependenciesAngularCli) == ''">^20.2.0</PackageJsonDevdependenciesAngularCli>
39
+ <PackageJsonDevdependenciesAngularCompilerCli Condition="$(PackageJsonDevdependenciesAngularCompilerCli) == ''">^20.2.0</PackageJsonDevdependenciesAngularCompilerCli>
40
+ <PackageJsonDevdependenciesTypesJasmine Condition="$(PackageJsonDevdependenciesTypesJasmine) == ''">~5.1.0</PackageJsonDevdependenciesTypesJasmine>
41
+ <PackageJsonDevdependenciesJasmineCore Condition="$(PackageJsonDevdependenciesJasmineCore) == ''">~5.9.0</PackageJsonDevdependenciesJasmineCore>
42
+ <PackageJsonDevdependenciesKarma Condition="$(PackageJsonDevdependenciesKarma) == ''">~6.4.0</PackageJsonDevdependenciesKarma>
43
+ <PackageJsonDevdependenciesKarmaChromeLauncher Condition="$(PackageJsonDevdependenciesKarmaChromeLauncher) == ''">~3.2.0</PackageJsonDevdependenciesKarmaChromeLauncher>
44
+ <PackageJsonDevdependenciesKarmaCoverage Condition="$(PackageJsonDevdependenciesKarmaCoverage) == ''">~2.2.0</PackageJsonDevdependenciesKarmaCoverage>
45
+ <PackageJsonDevdependenciesKarmaJasmine Condition="$(PackageJsonDevdependenciesKarmaJasmine) == ''">~5.1.0</PackageJsonDevdependenciesKarmaJasmine>
46
+ <PackageJsonDevdependenciesKarmaJasmineHtmlReporter Condition="$(PackageJsonDevdependenciesKarmaJasmineHtmlReporter) == ''">~2.1.0</PackageJsonDevdependenciesKarmaJasmineHtmlReporter>
47
+ <PackageJsonDevdependenciesTypescript Condition="$(PackageJsonDevdependenciesTypescript) == ''">~5.9.2</PackageJsonDevdependenciesTypescript>
48
+ </PropertyGroup>
49
+ </Project>
package-lock.json ADDED
The diff for this file is too large to render. See raw diff
 
package.json ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "pytrade",
3
+ "version": "0.0.0",
4
+ "scripts": {
5
+ "ng": "ng",
6
+ "start": "ng serve --host=127.0.0.1",
7
+ "build": "ng build",
8
+ "watch": "ng build --watch --configuration development",
9
+ "test": "ng test"
10
+ },
11
+ "prettier": {
12
+ "printWidth": 100,
13
+ "singleQuote": true,
14
+ "overrides": [
15
+ {
16
+ "files": "*.html",
17
+ "options": {
18
+ "parser": "angular"
19
+ }
20
+ }
21
+ ]
22
+ },
23
+ "private": true,
24
+ "dependencies": {
25
+ "@angular/cdk": "^20.2.1",
26
+ "@angular/common": "^20.2.0",
27
+ "@angular/compiler": "^20.2.0",
28
+ "@angular/core": "^20.2.0",
29
+ "@angular/forms": "^20.2.0",
30
+ "@angular/material": "^20.2.1",
31
+ "@angular/platform-browser": "^20.2.0",
32
+ "@angular/router": "^20.2.0",
33
+ "apexcharts": "^5.3.4",
34
+ "axios": "^1.11.0",
35
+ "jest-editor-support": "*",
36
+ "ng-apexcharts": "^2.0.1",
37
+ "rxjs": "~7.8.0",
38
+ "tslib": "^2.3.0",
39
+ "zone.js": "~0.15.0"
40
+ },
41
+ "devDependencies": {
42
+ "@angular/build": "^20.2.0",
43
+ "@angular/cli": "^20.2.0",
44
+ "@angular/compiler-cli": "^20.2.0",
45
+ "@types/jasmine": "~5.1.0",
46
+ "jasmine-core": "~5.9.0",
47
+ "karma": "~6.4.0",
48
+ "karma-chrome-launcher": "~3.2.0",
49
+ "karma-coverage": "~2.2.0",
50
+ "karma-jasmine": "~5.1.0",
51
+ "karma-jasmine-html-reporter": "~2.1.0",
52
+ "typescript": "~5.9.2"
53
+ }
54
+ }
public/44965755.jpg ADDED

Git LFS Details

  • SHA256: 726a93c5d17ae6adc52e3e7b4d4c26e9d014cbf9ba82509a1f731cb2ee1b73b1
  • Pointer size: 130 Bytes
  • Size of remote file: 61.7 kB
public/bgimg.png ADDED

Git LFS Details

  • SHA256: 022a0e7797432118716bb707998eaa3a5853cf2a9bce90c54ccb2b042b8fb295
  • Pointer size: 132 Bytes
  • Size of remote file: 1.44 MB
public/bgkey-opacity.png ADDED

Git LFS Details

  • SHA256: a63aee1ba82df3251257cbb0f1247c66693b3abec38f17ac264205bded40cc30
  • Pointer size: 131 Bytes
  • Size of remote file: 801 kB
public/bgkey.png ADDED

Git LFS Details

  • SHA256: 069690f2e2d05aef696d115c94d494287dbb2c8f43acc041a32f3194416cf05b
  • Pointer size: 131 Bytes
  • Size of remote file: 698 kB
public/bgvideo.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:61d87371c7239259e64e17998d41f2fe1bb52fd5d9dcaa419c887f9e51cae818
3
+ size 2263652
public/chatbot.png ADDED

Git LFS Details

  • SHA256: 15d0cdb227ff83301581f3cfdb7f6ebe2f4daef43ee1b560f7ec2e13f1ffa977
  • Pointer size: 130 Bytes
  • Size of remote file: 20 kB
public/desktop_img.png ADDED

Git LFS Details

  • SHA256: 26265c2f491212a284e2a0fb60c08bef32e80af12d0d376e621aee291ca64ebe
  • Pointer size: 132 Bytes
  • Size of remote file: 1.76 MB
public/favicon.ico ADDED

Git LFS Details

  • SHA256: cfe4d8ffb4aa59a98ba75c1395aa82b0678a1af6e23d7e6ca61a20936ddba4cf
  • Pointer size: 128 Bytes
  • Size of remote file: 791 Bytes
public/featureimg.jpg ADDED

Git LFS Details

  • SHA256: e1e2746128b709823134c5e64b1e1c2b11c0fe6d12b779fc96377b047578ceaa
  • Pointer size: 130 Bytes
  • Size of remote file: 55 kB
public/filter-img.png ADDED

Git LFS Details

  • SHA256: 6ae8c8a24cd98215376906ab296072e07382f54e8094c8e518494d72baa1e4ae
  • Pointer size: 132 Bytes
  • Size of remote file: 1.63 MB
public/final.png ADDED

Git LFS Details

  • SHA256: 5176c62d0d1c438276c188dbdd905a6a5ce24648de2dbe424dbf59fee6a3d17d
  • Pointer size: 132 Bytes
  • Size of remote file: 1.91 MB
public/logo.png ADDED

Git LFS Details

  • SHA256: 6822dd558a87ba2abd6d43a97acc832f9aa8efe7630c7fd3eb85e41afae7a8d0
  • Pointer size: 129 Bytes
  • Size of remote file: 3.99 kB
public/marketselect.jpg ADDED

Git LFS Details

  • SHA256: 911820019c1016f25965f22a56d3475329226eea59f2a232f8fe2fcb9fe17bc6
  • Pointer size: 131 Bytes
  • Size of remote file: 419 kB
public/marketselect.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5e761f128092c0b54cc74bb95529c01593d9423e21e9b16771fe0da458b23188
3
+ size 2022987
public/yfinance.png ADDED

Git LFS Details

  • SHA256: 066d02eb49cb691465d27d4978345b8d90b8372c9c31a6f1688c4baf752a3d02
  • Pointer size: 129 Bytes
  • Size of remote file: 5.64 kB
src/app/analysispage/analysispage.html ADDED
@@ -0,0 +1,291 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="analyse-container">
2
+
3
+
4
+ <mat-card>
5
+ <h1>Overall Score Board</h1>
6
+
7
+ <table>
8
+ <thead>
9
+ <tr>
10
+ <th>Company Name</th>
11
+ <th>Ticker</th>
12
+ <th>Overall Signal</th>
13
+ <th>Overall Score</th>
14
+ <th>Technical Analysis Score (80%)</th>
15
+ <th>Fundamental Analysis Score (15%)</th>
16
+ <th>News Score (5%)</th>
17
+ </tr>
18
+ </thead>
19
+ <tbody id="resultsTable">
20
+ <tr *ngFor="let scoreboard of result;let i = index">
21
+ <td style="cursor:pointer"
22
+ (click)="selectCompany(i)"
23
+ [ngClass]="{ 'active-td': activeCompany === i }"
24
+ >{{scoreboard.company_name}}</td>
25
+ <td>{{scoreboard.ticker}}</td>
26
+ <td>
27
+ <div class="dot"
28
+ [ngClass]="getClass(scoreboard.combined_overall_signal)"></div>
29
+ </td>
30
+ <td>{{scoreboard.combined_overall_score}}</td>
31
+ <td>{{scoreboard.overall_ta_score}}</td>
32
+ <td>{{scoreboard.fundamental_analysis.overall_fa_score}}</td>
33
+ <td>{{scoreboard.news_overall_score}}</td>
34
+ </tr>
35
+ </tbody>
36
+ </table>
37
+
38
+ </mat-card>
39
+
40
+
41
+ <mat-card>
42
+ <h1>Close Price Chart</h1>
43
+ <div class="chart-container">
44
+ <div>
45
+ <apx-chart [series]="chartOptions.series"
46
+ [chart]="chartOptions.chart"
47
+ [xaxis]="chartOptions.xaxis"
48
+ [yaxis]="chartOptions.yaxis"></apx-chart>
49
+ </div>
50
+ <div>
51
+ <!-- Include ApexCharts in your HTML file -->
52
+ <apx-chart [series]="overallChart.series"
53
+ [chart]="overallChart.chart"
54
+ [labels]="overallChart.labels"
55
+ [plotOptions]="overallChart.plotOptions"
56
+ [fill]="overallChart.fill"
57
+ [tooltip]="overallChart.tooltip"
58
+ [legend]="overallChart.legend">
59
+ </apx-chart>
60
+
61
+
62
+ </div>
63
+ </div>
64
+
65
+
66
+ </mat-card>
67
+
68
+
69
+ <mat-card>
70
+ <h1>Trade Recommendations</h1>
71
+ <ng-container>
72
+ <table>
73
+ <thead>
74
+ <tr>
75
+ <th>Current Price</th>
76
+ <th>Entry Point</th>
77
+ <th>Stop Loss</th>
78
+ <th>Target Price</th>
79
+ </tr>
80
+ </thead>
81
+ <tbody>
82
+ <tr>
83
+ <td>
84
+ <p style="font-size:2vw;">{{result[activeCompany].live_price}}</p>
85
+ <p [ngStyle]="{'color': result[activeCompany].price_change > 0 ? 'green' : (result[activeCompany].price_change < 0 ? 'red' : 'green')}">{{result[activeCompany].price_change}} ({{result[activeCompany].percentage_change}}%)</p>
86
+ </td>
87
+ <td>{{result[activeCompany].tradingInfo.entry_point}}</td>
88
+ <td>{{result[activeCompany].tradingInfo.stop_loss}}</td>
89
+ <td>{{result[activeCompany].tradingInfo.target_price}}</td>
90
+
91
+ </tr>
92
+ </tbody>
93
+ </table>
94
+
95
+ <table>
96
+ <thead>
97
+ <tr>
98
+ <th>Pivot Points</th>
99
+ <th>Support</th>
100
+ <th>Resistance</th>
101
+ <th>Remarks</th>
102
+ </tr>
103
+ </thead>
104
+ <tbody>
105
+ <tr>
106
+ <td>
107
+ <div>
108
+ {{result[activeCompany].tradingInfo.pivot_point}}&nbsp;&nbsp;({{result[activeCompany].tradingInfo.p1_pect}}%)
109
+ </div>
110
+ </td>
111
+ <td>
112
+ <div>
113
+ <span color="#ec2932!important"><b>S1:</b></span>&nbsp;&nbsp; {{result[activeCompany].tradingInfo.support1}}&nbsp;&nbsp;({{result[activeCompany].tradingInfo.s1_pect}}%)
114
+ </div>
115
+ <div>
116
+ <span color="#ec2932!important"><b>S2:</b></span>&nbsp;&nbsp; {{result[activeCompany].tradingInfo.support2}}&nbsp;&nbsp;({{result[activeCompany].tradingInfo.s2_pect}}%)
117
+ </div>
118
+ <div>
119
+ <span color="#ec2932!important"><b>S3:</b></span>&nbsp;&nbsp; {{result[activeCompany].tradingInfo.support3}}&nbsp;&nbsp;({{result[activeCompany].tradingInfo.s3_pect}}%)
120
+ </div>
121
+ </td>
122
+ <td>
123
+ <div>
124
+ <span color="#ec2932!important"><b>R1:</b></span>&nbsp;&nbsp; {{result[activeCompany].tradingInfo.resistance1}}&nbsp;&nbsp;({{result[activeCompany].tradingInfo.r1_pect}}%)
125
+ </div>
126
+ <div>
127
+ <span color="#ec2932!important"><b>R2:</b></span>&nbsp;&nbsp; {{result[activeCompany].tradingInfo.resistance2}}&nbsp;&nbsp;({{result[activeCompany].tradingInfo.r2_pect}}%)
128
+ </div>
129
+ <div>
130
+ <span color="#ec2932!important"><b>R3:</b></span>&nbsp;&nbsp; {{result[activeCompany].tradingInfo.resistance3}}&nbsp;&nbsp;({{result[activeCompany].tradingInfo.r3_pect}}%)
131
+ </div>
132
+ </td>
133
+
134
+ <td>{{result[activeCompany].tradingInfo.remarks}}</td>
135
+ </tr>
136
+ </tbody>
137
+ </table>
138
+
139
+
140
+ </ng-container>
141
+ </mat-card>
142
+
143
+
144
+
145
+
146
+ <mat-card>
147
+ <h1>Technical Analysis</h1>
148
+
149
+
150
+ <table>
151
+ <thead>
152
+ <tr>
153
+ <th style="cursor:pointer;"
154
+ *ngFor="let kv of result[activeCompany].final_trade_signal | keyvalue"
155
+ (click)="showStrategies(kv.key)"
156
+ [ngClass]="{ 'active-td': selectedIndicator === kv.key }">
157
+ {{ kv.key }}
158
+ </th>
159
+ </tr>
160
+ </thead>
161
+ <tbody>
162
+ <tr>
163
+ <td *ngFor="let kv of result[activeCompany].final_trade_signal | keyvalue">
164
+ <div class="dot"
165
+ [ngClass]="getClass(kv.value)"></div>
166
+ </td>
167
+ </tr>
168
+ </tbody>
169
+ </table>
170
+
171
+ <div class="strategy-chart-container">
172
+
173
+ <div class="strategy-container">
174
+
175
+ <ng-container *ngFor="let kv of result[activeCompany][selectedIndicator] | keyvalue">
176
+ <div class="strategy">
177
+ <div class="content" style="cursor:pointer;"
178
+ (click)="loadStrategiesChart(kv.key)"
179
+ [ngClass]="{ 'active-td': selectedStrategy === kv.key }">{{kv.key}}</div>
180
+ <!--<div class="dot"
181
+ [ngClass]="getClass(kv.value)"></div>-->
182
+
183
+ <div class="dot" [ngClass]="getClass(kv.value)"></div>
184
+ <span *ngIf="getClass(kv.value) === 'strategyvalue'">{{ kv.value }}</span>
185
+ </div>
186
+
187
+ </ng-container>
188
+
189
+ </div>
190
+
191
+ <div class="strategy-chart" *ngFor="let strategyCharts of strategyChart">
192
+ <apx-chart [series]="strategyCharts.series"
193
+ [chart]="strategyCharts.chart"
194
+ [xaxis]="strategyCharts.xaxis"
195
+ [yaxis]="strategyCharts.yaxis"
196
+ [stroke]="strategyCharts.stroke"
197
+ [tooltip]="strategyCharts.tooltip"
198
+ [annotations]="strategyCharts.annotations">
199
+ </apx-chart>
200
+ </div>
201
+ </div>
202
+
203
+
204
+ </mat-card>
205
+
206
+
207
+ <mat-card>
208
+ <h1>Fundamental Analysis</h1>
209
+
210
+ <table>
211
+ <thead>
212
+ <tr>
213
+ <th *ngFor="let kv of result[activeCompany].fundamental_analysis.fa_strategy | keyvalue">
214
+ {{ kv.key }}
215
+ </th>
216
+ </tr>
217
+ </thead>
218
+ <tbody>
219
+ <tr>
220
+ <td *ngFor="let kv of result[activeCompany].fundamental_analysis.fa_strategy | keyvalue">
221
+ <div class="dot"
222
+ [ngClass]="getClass(kv.value)"></div>
223
+ </td>
224
+ </tr>
225
+ </tbody>
226
+ </table>
227
+
228
+
229
+ <div class="fa-metrics">
230
+ <ng-container *ngFor="let kv of result[activeCompany].fundamental_analysis | keyvalue">
231
+ <div class="strategy-container" *ngIf="kv.key !== 'overall_fa_score'&& kv.key !== 'fa_strategy'">
232
+
233
+ <div class="fa-title">{{ kv.key }}</div>
234
+
235
+ <div class="fa-content" *ngIf="kv.value && typeof kv.value === 'object'">
236
+ <div class="metrics" *ngFor="let kvalue of kv.value | keyvalue">
237
+ <div>{{ kvalue.key }}</div>
238
+ <div>{{ kvalue.value }}</div>
239
+ </div>
240
+ </div>
241
+
242
+ </div>
243
+ </ng-container>
244
+ </div>
245
+
246
+
247
+
248
+
249
+
250
+ </mat-card>
251
+
252
+
253
+
254
+ <mat-card>
255
+ <h1>Candlestick Chart</h1>
256
+ <apx-chart [series]="candlestickChartOptions.series"
257
+ [chart]="candlestickChartOptions.chart"
258
+ [xaxis]="candlestickChartOptions.xaxis"
259
+ [yaxis]="candlestickChartOptions.yaxis"></apx-chart>
260
+
261
+ </mat-card>
262
+
263
+
264
+ <mat-card>
265
+ <h1>Predicted Close Price for next 15 days</h1>
266
+ <div class="strategy-container">
267
+ <p>Maximum Highest Price Prediction: {{result[activeCompany].ai_predicted_highest_price}}</p>
268
+ <p>Maximum Lowest Price Prediction: {{result[activeCompany].ai_predicted_lowest_price}}</p>
269
+ </div>
270
+ <apx-chart [series]="predictedChart.series"
271
+ [chart]="predictedChart.chart"
272
+ [xaxis]="predictedChart.xaxis">
273
+ </apx-chart>
274
+ </mat-card>
275
+
276
+ <mat-card>
277
+ <h1>Latest News</h1>
278
+ <div class="news-container">
279
+ <ng-container *ngFor="let news of result[activeCompany].news">
280
+
281
+ <div class="strategy-container">
282
+ <div class="dot"
283
+ [ngClass]="getClass(news.sentiment)"></div>
284
+ <a [href]="news.url">{{news.title}}</a>
285
+ <span>{{news.published}}</span>
286
+ </div>
287
+
288
+ </ng-container>
289
+ </div>
290
+ </mat-card>
291
+ </div>
src/app/analysispage/analysispage.scss ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .analyse-container{
2
+ width:94%;
3
+ padding: 3vw;
4
+ display:flex;
5
+ flex-direction:column;
6
+ gap:2vw;
7
+ }
8
+
9
+ mat-card {
10
+ background: #142133;
11
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.55), 0 2px 6px rgba(0, 0, 0, 0.35), 0 0 0 1px rgba(255, 255, 255, 0.04) inset;
12
+ padding: 2vw;
13
+
14
+
15
+ h1 {
16
+ color: #38bdf8 !important;
17
+ font-size: 1.5vw;
18
+ font-family: arial;
19
+ }
20
+ }
21
+
22
+ /* ---- Theme ---- */
23
+ :host {
24
+ --bg: #0f172a;
25
+ --card: #121a27;
26
+ --line: #243044;
27
+ --ink: #e2e8f0;
28
+ --dim: #94a3b8;
29
+ --head: #2a3a52;
30
+ --good: #22c55e;
31
+ --warn: #eab308;
32
+ --bad: #ef4444;
33
+ }
34
+
35
+
36
+ /* ---- Table base ---- */
37
+ table {
38
+ width: 100%;
39
+ border-collapse: collapse;
40
+ color: var(--ink);
41
+ background: var(--card);
42
+ /*border: 1px solid var(--line);
43
+ border-radius: 14px;*/ /* visible if you do not use .table-wrap */
44
+ overflow: hidden; /* keeps rounded corners on header */
45
+ }
46
+
47
+ thead th {
48
+ background: var(--head);
49
+ color: #d9e7ff;
50
+ font-weight: 700;
51
+ letter-spacing: .3px;
52
+ padding: 12px 14px;
53
+ text-align: left;
54
+ border-bottom: 1px solid var(--line);
55
+ font-family: arial;
56
+ }
57
+
58
+ tbody td {
59
+ padding: 12px 14px;
60
+ border-top: 1px solid var(--line);
61
+ vertical-align: middle;
62
+ }
63
+
64
+
65
+
66
+ .dot {
67
+ width: 1vw;
68
+ height: 1vw;
69
+ border-radius: 50%;
70
+ display: inline-block;
71
+ margin-right: 8px;
72
+ }
73
+
74
+ .green {
75
+ background: var(--good);
76
+ }
77
+
78
+ .yellow {
79
+ background: var(--warn);
80
+ }
81
+
82
+ .red {
83
+ background: var(--bad);
84
+ }
85
+
86
+ .strategy-container {
87
+ background-color: #334155;
88
+ /* border: 1px solid #334155;*/
89
+ padding: 15px;
90
+ border-radius: 10px;
91
+ color: #FFFFFF;
92
+ display: flex;
93
+ flex-direction: column;
94
+ gap: 2vw;
95
+ font-family: Arial;
96
+ width: 20vw;
97
+ /*margin-top: 2vw;*/
98
+
99
+ .strategy {
100
+ display: flex;
101
+ font-family: Arial;
102
+ justify-content: space-between;
103
+ }
104
+ }
105
+
106
+ .fa-metrics {
107
+ display: grid;
108
+ grid-template-columns: repeat(3, 1fr);
109
+ gap: 40px;
110
+ max-width: 75vw;
111
+ margin: auto;
112
+ }
113
+ .fa-title {
114
+ color: #38bdf8 !important;
115
+ }
116
+ .fa-content {
117
+ display: flex;
118
+ flex-direction:column;
119
+ gap:1vw;
120
+ }
121
+ .metrics {
122
+ display: flex;
123
+ justify-content: space-between;
124
+ }
125
+
126
+ .news-container {
127
+ display: grid;
128
+ grid-template-columns: repeat(4, 1fr);
129
+ gap: 1vw;
130
+
131
+ a {
132
+ color: inherit;
133
+ text-decoration: none;
134
+ font-family: Arial;
135
+ }
136
+ }
137
+
138
+ .chart-container {
139
+ display: flex;
140
+ background-color: #1e293b;
141
+ }
142
+ .strategy-chart-container {
143
+ display: flex;
144
+ align-items: center;
145
+ gap: 2vw;
146
+
147
+ .strategy-chart {
148
+ background-color: #FFFFFF;
149
+ box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
150
+ }
151
+ }
152
+
153
+ .active-td {
154
+ color: #38bdf8 !important;
155
+ font-weight:bold;
156
+ }
src/app/analysispage/analysispage.spec.ts ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { Analysispage } from './analysispage';
4
+
5
+ describe('Analysispage', () => {
6
+ let component: Analysispage;
7
+ let fixture: ComponentFixture<Analysispage>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [Analysispage]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(Analysispage);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
src/app/analysispage/analysispage.ts ADDED
@@ -0,0 +1,226 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Component, OnInit, inject } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { MatCardModule } from '@angular/material/card';
4
+ import { Location } from '@angular/common';
5
+ import { NgApexchartsModule } from 'ng-apexcharts';
6
+ import { ChartService } from './chart.service';
7
+
8
+ @Component({
9
+ selector: 'app-analysispage',
10
+ standalone: true,
11
+ imports: [CommonModule, MatCardModule, NgApexchartsModule],
12
+ templateUrl: './analysispage.html',
13
+ styleUrls: ['./analysispage.scss']
14
+ })
15
+ export class Analysispage implements OnInit {
16
+ private location = inject(Location);
17
+ result: any;
18
+ chartOptions: any;
19
+ candlestickChartOptions: any;
20
+ overallChart: any;
21
+ strategyChart: any;
22
+ predictedChart: any;
23
+ selectedIndicator:any = 'ADX';
24
+ selectedStrategy: any = 'ADX';
25
+ activeCompany: number = 0;
26
+ constructor(private chartService: ChartService) { }
27
+
28
+ ngOnInit(): void {
29
+ const s = this.location.getState() as { result?: unknown } | null;
30
+ this.result = s?.result ?? null;
31
+ console.log('Analysis result:', this.result);
32
+ this.loadCharts();
33
+ this.loadStrategiesChart('ADX');
34
+ }
35
+
36
+ showStrategies(selectedIndicator:any) {
37
+ this.selectedIndicator = selectedIndicator;
38
+ }
39
+
40
+ loadStrategiesChart(strategyName: any) {
41
+ this.selectedStrategy = strategyName;
42
+
43
+ this.strategyChart = this.chartService.getChartOptions(strategyName, this.result[this.activeCompany]);
44
+ console.log(this.strategyChart);
45
+ }
46
+
47
+ getClass(signal: any) {
48
+ if (typeof signal === 'string') {
49
+ switch (signal.toLowerCase()) {
50
+ case 'buy':
51
+ case 'good':
52
+ case 'positive':
53
+ case 'bullish':
54
+ return 'green';
55
+ case 'dbuy':
56
+ case 'bad':
57
+ case 'negative':
58
+ case 'bearish':
59
+ return 'red';
60
+ case 'neutral':
61
+ case 'none':
62
+ return 'yellow';
63
+ default:
64
+ return '';
65
+ }
66
+ } else {
67
+ return 'strategyvalue'
68
+ }
69
+ }
70
+
71
+ loadCharts() {
72
+ let closePrices = this.result[this.activeCompany].ohlc_data.map((data:any) => ({
73
+ x: new Date(data.x).getTime(),
74
+ y: data.y[3]
75
+ }));
76
+ this.chartOptions = {
77
+ series: [{
78
+ name: "Close Price",
79
+ data: closePrices
80
+ }],
81
+ chart: {
82
+ type: 'area',
83
+ height: 350,
84
+ width: 1200
85
+ },
86
+ xaxis: {
87
+ type: 'datetime',
88
+ labels: {
89
+ style: {
90
+ colors: '#ffffff'
91
+ },
92
+ },
93
+ },
94
+ yaxis: {
95
+ title: {
96
+ text: 'Close Price'
97
+ }
98
+ }
99
+ };
100
+
101
+ this.candlestickChartOptions = {
102
+ chart: {
103
+ type: 'candlestick',
104
+ height: 550,
105
+ width: 1700
106
+ },
107
+ series: [{
108
+ data: this.result[this.activeCompany].ohlc_data
109
+ }],
110
+ xaxis: {
111
+ type: 'datetime',
112
+ labels: {
113
+ style: {
114
+ colors: '#ffffff'
115
+ },
116
+ },
117
+ },
118
+ yaxis: {
119
+ opposite: true,
120
+ labels: {
121
+ style: {
122
+ colors: '#ffffff'
123
+ },
124
+ },
125
+ }
126
+ };
127
+
128
+ this.overallChart = {
129
+ series: [
130
+ this.result[this.activeCompany].overall_ta_score,
131
+ this.result[this.activeCompany].overall_fa_score,
132
+ this.result[this.activeCompany].news_overall_score
133
+ ], // Three values for the donut chart
134
+ chart: {
135
+ type: 'donut',
136
+ width: 500
137
+ },
138
+ labels: ['TA', 'FA', 'News'], // Set the labels to show on the chart
139
+ plotOptions: {
140
+ pie: {
141
+ donut: {
142
+ size: '60%', // Control the thickness of the donut
143
+ labels: {
144
+ show: true,
145
+ name: {
146
+ show: false
147
+ },
148
+ value: {
149
+ show: true, // Show values inside the donut chart
150
+ fontSize: '16px', // Font size for values
151
+ color: 'white' // White color for the values
152
+ },
153
+ total: {
154
+ show: true,
155
+ label: 'Total', // Label at the center
156
+ formatter: (w: any) => {
157
+ // Display the total value (sum of all slices)
158
+ return w.globals.seriesTotals.reduce((a: any, b: any) => a + b, 0) + '%';
159
+ }
160
+ }
161
+ }
162
+ }
163
+ }
164
+ },
165
+ fill: {
166
+ type: 'solid',
167
+ colors: ['#ff5733', '#33ff57', '#ffcc00'] // Colors for TA, FA, and News
168
+ },
169
+ tooltip: {
170
+ enabled: true, // Enable tooltips for the chart
171
+ fillSeriesColor: false,
172
+ theme: 'dark',
173
+ style: {
174
+ fontSize: '14px',
175
+ color: 'white' // White text color for tooltips
176
+ }
177
+ },
178
+ legend: {
179
+ show: true,
180
+ position: 'bottom', // Position the legend at the bottom
181
+ labels: {
182
+ useSeriesColors: true, // Use the series colors for legend
183
+ colors: ['white'] // White text color for legend
184
+ }
185
+ }
186
+ };
187
+
188
+
189
+
190
+ const prediction_prices = this.result[this.activeCompany]['prediction_prices']
191
+ const prediction_dates = this.result[this.activeCompany]['prediction_dates']
192
+
193
+ this.predictedChart = {
194
+ series: [
195
+ {
196
+ name: "Predicted Price",
197
+ data: prediction_prices.map((value: any) => Number(value.toFixed(2))),
198
+ color: '#28a745'
199
+ }
200
+
201
+ ],
202
+ chart: {
203
+ type: "area",
204
+ height: 460,
205
+ width: 1650
206
+ },
207
+ xaxis: {
208
+ categories: prediction_dates,
209
+ labels: {
210
+ style: {
211
+ colors: '#ffffff'
212
+ },
213
+ },
214
+ }
215
+ };
216
+
217
+ }
218
+
219
+
220
+ selectCompany(index: number) {
221
+ this.activeCompany = index;
222
+ this.loadCharts();
223
+ }
224
+
225
+
226
+ }
src/app/analysispage/chart.service.ts ADDED
@@ -0,0 +1,558 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Injectable } from '@angular/core';
2
+
3
+ @Injectable({
4
+ providedIn: 'root'
5
+ })
6
+ export class ChartService {
7
+
8
+ constructor() { }
9
+
10
+ getChartOptions(strategyName: any, fetchData: any): any[] {
11
+ const strategyConfig: any = {
12
+
13
+ 'RSI 14': {
14
+ panels: [
15
+ {
16
+ indicators: ['RSI 14'],
17
+ showAnnotations: false,
18
+ levels: [],
19
+ yaxisconfig: {
20
+ min: 0,
21
+ max: 100
22
+ }
23
+ }
24
+ ]
25
+ },
26
+ 'Overbought/Oversold': {
27
+ panels: [
28
+ {
29
+ indicators: ['RSI 14'],
30
+ showAnnotations: true,
31
+ levels: [
32
+ { value: 70, color: '#FF0000', label: 'Overbought (70)' },
33
+ { value: 30, color: '#008000', label: 'Oversold (30)' }
34
+ ],
35
+ yaxisconfig: {
36
+ min: 0,
37
+ max: 100
38
+ }
39
+ }
40
+ ]
41
+ },
42
+ 'RSI Swing Rejection': {
43
+ panels: [
44
+ {
45
+ indicators: ['RSI 14'],
46
+ showAnnotations: false,
47
+ levels: [],
48
+ yaxisconfig: {
49
+ min: 0,
50
+ max: 100
51
+ }
52
+ }
53
+ ]
54
+ },
55
+ 'RSI Divergence': {
56
+ panels: [
57
+ {
58
+ indicators: ['RSI 14'],
59
+ showAnnotations: false,
60
+ levels: [],
61
+ yaxisconfig: {
62
+ min: 0,
63
+ max: 100
64
+ }
65
+ }
66
+ ]
67
+ },
68
+ 'RSI 5/14 Crossover': {
69
+ panels: [
70
+ {
71
+ indicators: ['RSI 14', 'RSI 5'],
72
+ showAnnotations: false,
73
+ levels: [],
74
+ yaxisconfig: {
75
+ min: 0,
76
+ max: 100
77
+ }
78
+ }
79
+ ]
80
+ },
81
+ 'RSI Trend 50 Confirmation': {
82
+ panels: [
83
+ {
84
+ indicators: ['RSI 14'],
85
+ showAnnotations: true,
86
+ levels: [
87
+ { value: 70, color: '#FF0000', label: 'Overbought (70)' },
88
+ { value: 50, color: '#775DD0', label: 'RSI (50)' },
89
+ { value: 30, color: '#008000', label: 'Oversold (30)' }
90
+ ],
91
+ yaxisconfig: {
92
+ min: 0,
93
+ max: 100
94
+ }
95
+ }
96
+ ]
97
+ },
98
+ 'Mean Reversion': {
99
+ panels: [
100
+ {
101
+ indicators: ['RSI 14'],
102
+ showAnnotations: true,
103
+ levels: [
104
+ { value: 80, color: '#FF0000', label: 'Overbought (80)' },
105
+ { value: 20, color: '#008000', label: 'Oversold (20)' }
106
+ ],
107
+ yaxisconfig: {
108
+ min: 0,
109
+ max: 100
110
+ }
111
+ }
112
+ ]
113
+ },
114
+ 'RSI_Bollinger Band': {
115
+ panels: [
116
+ {
117
+ indicators: ['RSI 14'],
118
+ showAnnotations: true,
119
+ levels: [
120
+ { value: 70, color: '#FF0000', label: 'Overbought (70)' },
121
+ { value: 30, color: '#008000', label: 'Oversold (30)' }
122
+ ],
123
+ yaxisconfig: {
124
+ min: 0,
125
+ max: 100
126
+ }
127
+ },
128
+ {
129
+ indicators: ['Close', 'UpperBB', 'LowerBB'],
130
+ showAnnotations: false,
131
+ levels: [],
132
+ yaxisconfig: {} // auto-scaling
133
+ }
134
+ ]
135
+ },
136
+ 'RSI_MA': {
137
+ panels: [
138
+ {
139
+ indicators: ['RSI 14'],
140
+ showAnnotations: true,
141
+ levels: [
142
+ { value: 70, color: '#FF0000', label: 'Overbought (70)' },
143
+ { value: 30, color: '#008000', label: 'Oversold (30)' }
144
+ ],
145
+ yaxisconfig: {
146
+ min: 0,
147
+ max: 100
148
+ }
149
+ },
150
+ {
151
+ indicators: ['Close', 'MA_20'],
152
+ showAnnotations: false,
153
+ levels: [],
154
+ yaxisconfig: {} // auto-scaling
155
+ }
156
+ ]
157
+ },
158
+ 'MACD': {
159
+ panels: [
160
+ {
161
+ indicators: ['MACDLine'],
162
+ showAnnotations: false,
163
+ levels: [],
164
+ yaxisconfig: {}
165
+ }
166
+ ]
167
+ },
168
+ 'MACD Line Crossover': {
169
+ panels: [
170
+ {
171
+ indicators: ['MACDLine', 'MACDSignalLine', 'MACDHistogram'],
172
+ showAnnotations: false,
173
+ levels: [],
174
+ yaxisconfig: {}
175
+ }
176
+ ]
177
+ },
178
+ 'MACD Zero-Line Crossover': {
179
+ panels: [
180
+ {
181
+ indicators: ['MACDLine'],
182
+ showAnnotations: true,
183
+ levels: [{ value: 0, color: '#FF0000', label: 'MACD ZeroLine' },],
184
+ yaxisconfig: {}
185
+ }
186
+ ]
187
+ },
188
+ 'MACD Momentum': {
189
+ panels: [
190
+ {
191
+ indicators: ['MACDLine', 'MACDSignalLine', 'MACDHistogram'],
192
+ showAnnotations: false,
193
+ levels: [{ value: 0, color: '#FF0000', label: 'MACD ZeroLine' },],
194
+ yaxisconfig: {}
195
+ }
196
+ ]
197
+ },
198
+ 'ATR': {
199
+ panels: [
200
+ {
201
+ indicators: ['ATRValue'],
202
+ showAnnotations: false,
203
+ levels: [],
204
+ yaxisconfig: {} // auto-scaling
205
+ }
206
+ ]
207
+ },
208
+ 'ATR Breakout': {
209
+ panels: [
210
+ {
211
+ indicators: ['ATRValue'],
212
+ showAnnotations: false,
213
+ levels: [],
214
+ yaxisconfig: {} // auto-scaling
215
+ },
216
+ {
217
+ indicators: ['Close'],
218
+ showAnnotations: false,
219
+ levels: [],
220
+ yaxisconfig: {} // auto-scaling for Close Price
221
+ }
222
+ ]
223
+ },
224
+ 'ATR Expansion': {
225
+ panels: [
226
+ {
227
+ indicators: ['ATRValue'],
228
+ showAnnotations: false,
229
+ levels: [],
230
+ yaxisconfig: {} // auto-scaling
231
+ }
232
+ ]
233
+ },
234
+ 'ATR Squeeze': {
235
+ panels: [
236
+ {
237
+ indicators: ['ATRValue'],
238
+ showAnnotations: false,
239
+ levels: [],
240
+ yaxisconfig: {} // auto-scaling
241
+ }
242
+ ]
243
+ },
244
+ 'ATR Trend Reversal': {
245
+ panels: [
246
+ {
247
+ indicators: ['ATRValue'],
248
+ showAnnotations: false,
249
+ levels: [],
250
+ yaxisconfig: {} // auto-scaling
251
+ }
252
+ ]
253
+ },
254
+ 'EMA 20': {
255
+ panels: [
256
+ {
257
+ indicators: ['EMA 20'],
258
+ showAnnotations: false,
259
+ levels: [],
260
+ yaxisconfig: {} // auto-scaling
261
+ }
262
+ ]
263
+ },
264
+
265
+ 'EMA 50': {
266
+ panels: [
267
+ {
268
+ indicators: ['EMA 50'],
269
+ showAnnotations: false,
270
+ levels: [],
271
+ yaxisconfig: {} // auto-scaling
272
+ }
273
+ ]
274
+ },
275
+
276
+ 'EMA Crossover': {
277
+ panels: [
278
+ {
279
+ indicators: ['EMA 20', 'EMA 50'],
280
+ showAnnotations: false,
281
+ levels: [],
282
+ yaxisconfig: {} // auto-scaling
283
+ }
284
+ ]
285
+ },
286
+ 'EMA Price Crossover': {
287
+ panels: [
288
+ {
289
+ indicators: ['EMA 20', 'Close'],
290
+ showAnnotations: false,
291
+ levels: [],
292
+ yaxisconfig: {} // auto-scaling
293
+ }
294
+ ]
295
+ },
296
+ 'Triple EMA': {
297
+ panels: [
298
+ {
299
+ indicators: ['EMA 5', 'EMA 20', 'EMA 50'],
300
+ showAnnotations: false,
301
+ levels: [],
302
+ yaxisconfig: {} // auto-scaling
303
+ }
304
+ ]
305
+ },
306
+ 'ADX': {
307
+ panels: [
308
+ {
309
+ indicators: ['ADX_Indicator'],
310
+ showAnnotations: false,
311
+ levels: [],
312
+ yaxisconfig: {
313
+ min: 0,
314
+ max: 100
315
+ }
316
+ }
317
+ ]
318
+ },
319
+
320
+ 'ADX + DI Crossover': {
321
+ panels: [
322
+ {
323
+ indicators: ['ADX_Indicator', 'PLUS_DI', 'MINUS_DI'],
324
+ showAnnotations: false,
325
+ levels: [],
326
+ yaxisconfig: {
327
+ min: 0,
328
+ max: 100
329
+ }
330
+ }
331
+ ]
332
+ },
333
+ 'ADX Divergence': {
334
+ panels: [
335
+ {
336
+ indicators: ['ADX_Indicator'],
337
+ showAnnotations: false,
338
+ levels: [],
339
+ yaxisconfig: {
340
+ min: 0,
341
+ max: 100
342
+ }
343
+ },
344
+ {
345
+ indicators: ['Close'],
346
+ showAnnotations: false,
347
+ levels: [],
348
+ yaxisconfig: {} // auto-scale for price
349
+ }
350
+ ]
351
+ },
352
+ 'ADX Slope': {
353
+ panels: [
354
+ {
355
+ indicators: ['ADX_Indicator'],
356
+ showAnnotations: false,
357
+ levels: [],
358
+ yaxisconfig: {
359
+ min: 0,
360
+ max: 100
361
+ }
362
+ }
363
+ ]
364
+ },
365
+ 'ADX Breakout': {
366
+ panels: [
367
+ {
368
+ indicators: ['ADX_Indicator'],
369
+ showAnnotations: false,
370
+ levels: [],
371
+ yaxisconfig: {
372
+ min: 0,
373
+ max: 100
374
+ }
375
+ },
376
+ {
377
+ indicators: ['Close'],
378
+ showAnnotations: false,
379
+ levels: [],
380
+ yaxisconfig: {} // auto-scale for price
381
+ }
382
+ ]
383
+ },
384
+ 'Fibonacci Retracement Bounce': {
385
+ panels: [
386
+ {
387
+ indicators: ['Candlestick'],
388
+ showAnnotations: true,
389
+ levels: [
390
+ { value: 0.382, color: '#00008B', label: '38.2%' },
391
+ { value: 0.5, color: '#FF0000', label: '50%' },
392
+ { value: 0.618, color: '#FF5722', label: '61.8%' }
393
+ ],
394
+ yaxisconfig: {} // auto-scaling
395
+ }
396
+ ]
397
+ },
398
+
399
+ 'Fibonacci Breakout': {
400
+ panels: [
401
+ {
402
+ indicators: ['Candlestick'],
403
+ showAnnotations: true,
404
+ levels: [],
405
+ yaxisconfig: {} // auto-scaling
406
+ }
407
+ ]
408
+ },
409
+
410
+ 'Fibonacci Confluence': {
411
+ panels: [
412
+ {
413
+ indicators: ['Close', 'EMA9'],
414
+ showAnnotations: true,
415
+ levels: [], // dynamically filled
416
+ yaxisconfig: {} // auto-scaling
417
+ }
418
+ ]
419
+ },
420
+
421
+ 'Golden Pocket Reversal': {
422
+ panels: [
423
+ {
424
+ indicators: ['Candlestick'],
425
+ showAnnotations: true,
426
+ levels: [
427
+ { value: fetchData.FIB_61_8, color: '#FF0000', label: '61.8%' },
428
+ { value: fetchData.FIB_65, color: '#FFC107', label: '65%' }
429
+ ],
430
+ yaxisconfig: {} // auto-scaling
431
+ }
432
+ ]
433
+ },
434
+
435
+ 'BB Squeeze': {
436
+ panels: [
437
+ {
438
+ indicators: ['Close', 'UpperBB', 'LowerBB'],
439
+ showAnnotations: false,
440
+ levels: [],
441
+ yaxisconfig: {} // auto-scaling
442
+ }
443
+ ]
444
+ },
445
+
446
+ 'BB Breakout': {
447
+ panels: [
448
+ {
449
+ indicators: ['Close', 'UpperBB', 'LowerBB'],
450
+ showAnnotations: false,
451
+ levels: [],
452
+ yaxisconfig: {} // auto-scaling
453
+ }
454
+ ]
455
+ },
456
+
457
+
458
+ 'BB Reversal': {
459
+ panels: [
460
+ {
461
+ indicators: ['Close', 'UpperBB', 'LowerBB'],
462
+ showAnnotations: false,
463
+ levels: [],
464
+ yaxisconfig: {} // auto-scaling
465
+ }
466
+ ]
467
+ },
468
+
469
+
470
+
471
+ };
472
+
473
+ const config = strategyConfig[strategyName];
474
+
475
+ if (strategyName === 'Fibonacci Breakout') {
476
+ config.panels[0].levels = [
477
+ { value: fetchData.FIB_61_8, color: '#FF5722', label: '61.8% Breakout' }
478
+ ];
479
+ }
480
+
481
+ // For Fibonacci Retracement Bounce, convert levels to price-based annotations
482
+ if (strategyName === 'Fibonacci Retracement Bounce') {
483
+ config.panels[0].levels = [
484
+ { value: fetchData.FIB_38_2, color: '#00008B', label: '38.2%' },
485
+ { value: fetchData.FIB_50, color: '#FF0000', label: '50%' },
486
+ { value: fetchData.FIB_61_8, color: '#FF5722', label: '61.8%' }
487
+ ];
488
+ }
489
+
490
+ if (strategyName === 'Fibonacci Confluence') {
491
+ config.panels[0].levels = [
492
+ { value: fetchData.FIB_61_8, color: '#FF5722', label: '61.8% Confluence' }
493
+ ];
494
+ }
495
+
496
+
497
+ const chartOptionsArray = config.panels.map((panel: any) => {
498
+ const referenceData = fetchData[panel.indicators[0]];
499
+ const categories = Object.keys(referenceData);
500
+
501
+ const series = panel.indicators.map((indicator: string) => {
502
+ const indicatorData = fetchData[indicator];
503
+
504
+ if (indicator === 'Candlestick') {
505
+ return {
506
+ name: 'Candlestick',
507
+ type: 'candlestick',
508
+ data: indicatorData // already in [{x, y: [o,h,l,c]}] format
509
+ };
510
+ }
511
+
512
+ return {
513
+ name: indicator,
514
+ type: indicator === 'MACDHistogram' ? 'bar' : 'line',
515
+ data: indicatorData ? Object.entries(indicatorData).map(([x, y]) => ({ x, y })) : []
516
+ };
517
+ });
518
+
519
+ const annotations = panel.showAnnotations ? {
520
+ yaxis: panel.levels.map((level: any) => ({
521
+ y: level.value,
522
+ borderColor: level.color,
523
+ label: {
524
+ borderColor: level.color,
525
+ style: {
526
+ color: '#fff',
527
+ background: level.color
528
+ },
529
+ text: level.label
530
+ }
531
+ }))
532
+ } : {};
533
+
534
+ return {
535
+ series: series,
536
+ chart: {
537
+ type: 'line',
538
+ height: 500,
539
+ width: 1300
540
+ },
541
+ xaxis: {
542
+ categories: categories
543
+ },
544
+ yaxis: panel.yaxisconfig || {},
545
+ stroke: {
546
+ curve: 'smooth',
547
+ width: 2
548
+ },
549
+ annotations: annotations
550
+ };
551
+ });
552
+
553
+ return chartOptionsArray;
554
+ }
555
+
556
+
557
+
558
+ }
src/app/app-module.ts ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core';
2
+ import { BrowserModule } from '@angular/platform-browser';
3
+
4
+ import { AppRoutingModule } from './app-routing-module';
5
+ import { App } from './app';
6
+ import { Homepage } from './homepage/homepage';
7
+ import { RouterModule, Routes } from '@angular/router';
8
+
9
+
10
+ import { CommonModule } from '@angular/common';
11
+ import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
12
+ import { HttpClientModule } from '@angular/common/http';
13
+
14
+ import { FormsModule } from '@angular/forms';
15
+ import { MatFormFieldModule } from '@angular/material/form-field'; // Import mat-form-field module
16
+ import { MatInputModule } from '@angular/material/input';
17
+ // Import mat-input module
18
+
19
+
20
+ @NgModule({
21
+ declarations: [
22
+ App,
23
+ Homepage,
24
+
25
+
26
+
27
+ ],
28
+ imports: [
29
+ BrowserModule,
30
+ AppRoutingModule,
31
+ CommonModule,
32
+ ReactiveFormsModule,
33
+ HttpClientModule,
34
+ FormsModule,
35
+ MatFormFieldModule,
36
+ MatInputModule
37
+
38
+ //RouterModule.forRoot(routes, {
39
+ // scrollPositionRestoration: 'enabled',
40
+ // anchorScrolling: 'enabled',
41
+ // bindToComponentInputs: true
42
+ //})
43
+ ],
44
+ providers: [
45
+ provideBrowserGlobalErrorListeners()
46
+ ],
47
+ bootstrap: [App]
48
+ })
49
+ export class AppModule { }
src/app/app-routing-module.ts ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { NgModule } from '@angular/core';
2
+ import { RouterModule, Routes } from '@angular/router';
3
+ import { MarketSelectComponent } from './marketselect/marketselect';
4
+ import { Homepage } from './homepage/homepage';
5
+ import { Analysispage } from './analysispage/analysispage';
6
+ import { Chatbot } from './chatbot/chatbot';
7
+ import { ToolspageComponent } from './toolspage/toolspage.component';
8
+ import { Screenerpage } from './screenerpage/screenerpage';
9
+
10
+ const routes: Routes = [
11
+ { path: '', component: Homepage },
12
+ { path: 'home', component: Homepage },
13
+ { path: 'tools', component: MarketSelectComponent },
14
+ { path: 'analysepage', component: Analysispage },
15
+ { path: 'chatbot', component: Chatbot },
16
+ { path: 'screener', component: Screenerpage },
17
+ { path: 'marketselect', component: ToolspageComponent },
18
+ { path: '**', redirectTo: '' }
19
+ ];
20
+
21
+
22
+
23
+
24
+ @NgModule({
25
+ imports: [RouterModule.forRoot(routes)],
26
+ exports: [RouterModule]
27
+ })
28
+ export class AppRoutingModule { }
src/app/app.html ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="navigation-container">
2
+ <div class="nav-content">
3
+ <img src="logo.png" alt="PyTrade Logo" class="logo-img">
4
+ <h1 class="logo-title">PY-TRADE</h1>
5
+ <div style="display: flex; gap: 2vw; margin-left: 47vw;align-self:flex-start;">
6
+ <p class="menu-item">Markets</p>
7
+ <p class="menu-item">Community</p>
8
+ <p class="menu-item">AI Assistant</p>
9
+
10
+ </div>
11
+
12
+ <div class="user-avatar">
13
+ <img src="https://cdn-icons-png.flaticon.com/512/847/847969.png" alt="User Image">
14
+ </div>
15
+ </div>
16
+
17
+ </div>
18
+
19
+ <router-outlet></router-outlet>
src/app/app.scss ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Navigation Styles
2
+ .navigation-container {
3
+ background: linear-gradient(180deg, #0f0f0f, #0f0f0f00);
4
+ position: fixed;
5
+ width: 98%;
6
+ height: 10vw;
7
+ padding: 1vw;
8
+ .nav-content
9
+
10
+ {
11
+ display: flex;
12
+ gap: 2vw;
13
+ align-items: center;
14
+ justify-content: space-between;
15
+ .logo-img
16
+
17
+ {
18
+ width: 6vw;
19
+ height: 6vw;
20
+ border-radius: 50%;
21
+ box-shadow: 0 0 15px rgba(255, 255, 255, 0.8);
22
+ }
23
+
24
+ .logo-title {
25
+ font-size: 3vw;
26
+ }
27
+
28
+ .menu-item {
29
+ font-size: 1vw;
30
+ }
31
+
32
+ .user-avatar {
33
+ width: 2.5vw; /* Size of the avatar */
34
+ height: 2.5vw;
35
+ border-radius: 50%; /* Makes it circular */
36
+ overflow: hidden; /* Ensures image stays within circle */
37
+ display: inline-block;
38
+ position: relative;
39
+ background: linear-gradient(135deg, #38bdf8, #712d74); /* Gradient border */
40
+ padding: 3px; /* Space for gradient border */
41
+ align-self: flex-start
42
+ }
43
+
44
+ .user-avatar img {
45
+ width: 100%;
46
+ height: 100%;
47
+ border-radius: 50%; /* Keep image circular */
48
+ object-fit: cover; /* Cover the container without distortion */
49
+ }
50
+
51
+ }
52
+ }
src/app/app.spec.ts ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { TestBed } from '@angular/core/testing';
2
+ import { RouterModule } from '@angular/router';
3
+ import { App } from './app';
4
+
5
+ describe('App', () => {
6
+ beforeEach(async () => {
7
+ await TestBed.configureTestingModule({
8
+ imports: [
9
+ RouterModule.forRoot([])
10
+ ],
11
+ declarations: [
12
+ App
13
+ ],
14
+ }).compileComponents();
15
+ });
16
+
17
+ it('should create the app', () => {
18
+ const fixture = TestBed.createComponent(App);
19
+ const app = fixture.componentInstance;
20
+ expect(app).toBeTruthy();
21
+ });
22
+
23
+ it('should render title', () => {
24
+ const fixture = TestBed.createComponent(App);
25
+ fixture.detectChanges();
26
+ const compiled = fixture.nativeElement as HTMLElement;
27
+ expect(compiled.querySelector('h1')?.textContent).toContain('Hello, Pytrade');
28
+ });
29
+ });
src/app/app.ts ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Component, signal } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'app-root',
5
+ templateUrl: './app.html',
6
+ standalone: false,
7
+ styleUrl: './app.scss'
8
+ })
9
+ export class App {
10
+ protected readonly title = signal('Pytrade');
11
+ }
src/app/chatbot/chatbot.html ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="chatbot-container">
2
+ <div class="chatbox">
3
+ <div *ngFor="let message of messages" class="message">
4
+ <div class="user-message"><strong>User:</strong> {{ message.user }}</div>
5
+ <div class="bot-response"><strong>Bot:</strong> {{ message.bot }}</div>
6
+ </div>
7
+ </div>
8
+ <input [(ngModel)]="userQuestion" placeholder="Ask a question..." />
9
+ <button (click)="getChatbotResponse()">Ask</button>
10
+ </div>
src/app/chatbot/chatbot.scss ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* General Container */
2
+ .chatbot-container {
3
+ max-width: 400px;
4
+ margin: 0 auto;
5
+ padding: 20px;
6
+ border-radius: 15px;
7
+ background-color: #f4f7fc;
8
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
9
+ overflow: hidden;
10
+ font-family: 'Arial', sans-serif;
11
+ }
12
+
13
+ /* Chatbox Container */
14
+ .chatbox {
15
+ max-height: 300px;
16
+ overflow-y: auto;
17
+ margin-bottom: 20px;
18
+ padding-right: 10px;
19
+ border-bottom: 2px solid #dcdfe6;
20
+ padding-left: 15px;
21
+ background: #fff;
22
+ border-radius: 10px;
23
+ }
24
+
25
+ /* Individual Message Styling */
26
+ .message {
27
+ margin-bottom: 15px;
28
+ display: flex;
29
+ flex-direction: column;
30
+ align-items: flex-start;
31
+ }
32
+
33
+ .user-message {
34
+ background-color: #e0f7fa;
35
+ padding: 8px 12px;
36
+ border-radius: 10px;
37
+ margin-bottom: 5px;
38
+ max-width: 80%;
39
+ align-self: flex-start;
40
+ font-size: 14px;
41
+ color: #00796b;
42
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
43
+ animation: fadeIn 0.5s ease;
44
+ }
45
+
46
+ .bot-response {
47
+ background-color: #e8f5e9;
48
+ padding: 8px 12px;
49
+ border-radius: 10px;
50
+ max-width: 80%;
51
+ align-self: flex-end;
52
+ font-size: 14px;
53
+ color: #388e3c;
54
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
55
+ animation: fadeIn 0.5s ease;
56
+ }
57
+
58
+ /* Input Box Styling */
59
+ input {
60
+ width: 80%;
61
+ padding: 12px;
62
+ font-size: 14px;
63
+ border-radius: 25px;
64
+ border: 1px solid #ccc;
65
+ margin-right: 10px;
66
+ background-color: #ffffff;
67
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
68
+ }
69
+
70
+ button {
71
+ padding: 12px;
72
+ font-size: 14px;
73
+ background-color: #00796b;
74
+ color: white;
75
+ border: none;
76
+ border-radius: 25px;
77
+ cursor: pointer;
78
+ transition: all 0.3s;
79
+ }
80
+
81
+ button:hover {
82
+ background-color: #004d40;
83
+ transform: scale(1.05);
84
+ }
85
+
86
+ button:focus {
87
+ outline: none;
88
+ }
89
+
90
+ /* Scrollbar Styling */
91
+ .chatbox::-webkit-scrollbar {
92
+ width: 8px;
93
+ }
94
+
95
+ .chatbox::-webkit-scrollbar-thumb {
96
+ background-color: #00796b;
97
+ border-radius: 10px;
98
+ }
99
+
100
+ .chatbox::-webkit-scrollbar-track {
101
+ background-color: #f4f7fc;
102
+ }
103
+
104
+ /* Loading Spinner */
105
+ .loader {
106
+ border: 4px solid #f3f3f3;
107
+ border-top: 4px solid #00796b;
108
+ border-radius: 50%;
109
+ width: 24px;
110
+ height: 24px;
111
+ animation: spin 1s linear infinite;
112
+ margin: 0 auto;
113
+ }
114
+
115
+ @keyframes spin {
116
+ 0% {
117
+ transform: rotate(0deg);
118
+ }
119
+
120
+ 100% {
121
+ transform: rotate(360deg);
122
+ }
123
+ }
124
+
125
+ @keyframes fadeIn {
126
+ 0% {
127
+ opacity: 0;
128
+ }
129
+
130
+ 100% {
131
+ opacity: 1;
132
+ }
133
+ }
src/app/chatbot/chatbot.spec.ts ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { Chatbot } from './chatbot';
4
+
5
+ describe('Chatbot', () => {
6
+ let component: Chatbot;
7
+ let fixture: ComponentFixture<Chatbot>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ declarations: [Chatbot]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(Chatbot);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
src/app/chatbot/chatbot.ts ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { CommonModule } from '@angular/common';
2
+ import { Component } from '@angular/core';
3
+ import { FormsModule } from '@angular/forms';
4
+ import axios from 'axios';
5
+
6
+ @Component({
7
+ selector: 'app-chatbot',
8
+ standalone: true,
9
+ imports: [FormsModule],
10
+ templateUrl: './chatbot.html',
11
+ styleUrl: './chatbot.scss'
12
+ })
13
+ export class Chatbot {
14
+ userQuestion: string = ''; // Holds the user's question
15
+ chatbotAnswer: string = ''; // Holds the chatbot's answer
16
+
17
+ // Define messages array to store conversation
18
+ messages: { user: string, bot: string }[] = []; // This is the missing property
19
+
20
+ // Handle user input and make API call to backend
21
+ async getChatbotResponse() {
22
+ if (this.userQuestion.trim()) {
23
+ // Add user's question to the messages array
24
+ this.messages.push({ user: this.userQuestion, bot: '...' });
25
+
26
+ try {
27
+ // Make API call to backend for the answer
28
+ const response = await axios.post('http://127.0.0.1:5000/ask', {
29
+ question: this.userQuestion
30
+ });
31
+
32
+ // Get the answer from the response and update the chatbot response
33
+ this.chatbotAnswer = response.data.answer;
34
+
35
+ // Add the chatbot's answer to the messages array
36
+ this.messages[this.messages.length - 1].bot = this.chatbotAnswer;
37
+
38
+ // Clear the user question input
39
+ this.userQuestion = '';
40
+
41
+ } catch (error) {
42
+ console.error('Error while getting response from chatbot API:', error);
43
+ // Handle error gracefully by adding an error message in the conversation
44
+ this.messages.push({ user: this.userQuestion, bot: 'Sorry, I am unable to get an answer right now.' });
45
+ this.userQuestion = '';
46
+ }
47
+ }
48
+ }
49
+ }
src/app/homepage/homepage.html ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!--Fixed Navigation-->
2
+
3
+ <!--<div class="navigation-container">
4
+ <div class="nav-content">
5
+ <img src="logo.png" alt="PyTrade Logo" class="logo-img">
6
+ <h1 class="logo-title">PY-TRADE</h1>
7
+ <div style="display: flex; gap: 2vw; margin-left: 47vw;align-self:flex-start;">
8
+ <p class="menu-item">Markets</p>
9
+ <p class="menu-item">Community</p>
10
+ <p class="menu-item">AI Assistant</p>
11
+
12
+ </div>
13
+
14
+ <div class="user-avatar">
15
+ <img src="https://cdn-icons-png.flaticon.com/512/847/847969.png" alt="User Image">
16
+ </div>
17
+ </div>
18
+
19
+ </div>-->
20
+
21
+ <!--Landing Page-->
22
+ <div class="homepage-container">
23
+
24
+ <h1 class="py-title">Unlock the Future of Trading</h1>
25
+ <p class="py-quote">Empower your decisions with data, and turn insights into profitable action.</p>
26
+ <button class="get-started-btn" routerLink="/marketselect">
27
+ Get Started
28
+ </button>
29
+ </div>
30
+
31
+
32
+ <!--Features container-->
33
+ <div class="key-feature-container">
34
+ <h1>Key Features</h1>
35
+
36
+ <div class="features">
37
+ <div class="feature-card">
38
+ <span>📊</span>
39
+ <div class="feature-title">Technical Analysis</div>
40
+ <div class="feature-detail">
41
+ Technical analysis helps you make informed decisions by analyzing historical market data like price and volume.
42
+ It includes charts, indicators, and price patterns to forecast market movements.
43
+ </div>
44
+ </div>
45
+
46
+ <div class="feature-card">
47
+ <span>💹</span>
48
+ <div class="feature-title">Fundamental Analysis</div>
49
+ <div class="feature-detail">
50
+ Fundamental analysis helps evaluate the financial health of a company by analyzing financial statements,
51
+ earnings, revenue, and market conditions. It assists in determining the intrinsic value of stocks for long-term investments.
52
+ </div>
53
+ </div>
54
+
55
+ <div class="feature-card">
56
+ <span>📰</span>
57
+ <div class="feature-title">Market News Sentiment Analysis</div>
58
+ <div class="feature-detail">
59
+ Market news sentiment analysis evaluates the mood and sentiment of market participants by analyzing news,
60
+ social media, and other relevant information. It helps predict potential market reactions to news events.
61
+ </div>
62
+ </div>
63
+
64
+ <div class="feature-card">
65
+ <span>🔮</span>
66
+ <div class="feature-title">Predictions with LSTM</div>
67
+ <div class="feature-detail">
68
+ Long Short-Term Memory (LSTM) models predict future price movements using historical market data.
69
+ These models are highly effective in capturing patterns and trends for more accurate predictions in volatile markets.
70
+ </div>
71
+ </div>
72
+
73
+ <div class="feature-card">
74
+ <span>⚡</span>
75
+ <div class="feature-title">Live Data</div>
76
+ <div class="feature-detail">
77
+ Access to live market data ensures you stay updated with the latest prices, volumes, and other important metrics
78
+ in real-time, enabling you to make quick, informed decisions.
79
+ </div>
80
+ </div>
81
+
82
+ <div class="feature-card">
83
+ <span>💡</span>
84
+ <div class="feature-title">Trade Recommendations</div>
85
+ <div class="feature-detail">
86
+ Get personalized trade recommendations based on your trading strategy and market analysis.
87
+ These recommendations are powered by advanced algorithms that analyze historical and real-time data.
88
+ </div>
89
+ </div>
90
+
91
+ <div class="feature-card">
92
+ <span>📉</span>
93
+ <div class="feature-title">Chart Analysis</div>
94
+ <div class="feature-detail">
95
+ Analyze various types of charts like candlestick, line, and bar charts to identify trends, support, resistance levels,
96
+ and chart patterns. This helps in making better trading decisions.
97
+ </div>
98
+ </div>
99
+
100
+ <div class="feature-card">
101
+ <span>🔔</span>
102
+ <div class="feature-title">Smart Alerts</div>
103
+ <div class="feature-detail">
104
+ Set smart alerts to get notified about market events, price movements, or specific conditions,
105
+ so you never miss important trading opportunities.
106
+ </div>
107
+ </div>
108
+
109
+ <div class="feature-card">
110
+ <span>🤖</span>
111
+ <div class="feature-title">AI Assistant</div>
112
+ <div class="feature-detail">
113
+ The AI Assistant provides insights, analyzes patterns, and helps you make data-driven decisions with the power of artificial intelligence,
114
+ making trading more efficient and less stressful.
115
+ </div>
116
+ </div>
117
+ </div>
118
+
119
+ </div>
120
+
121
+
122
+
123
+ <footer class="footer">
124
+ <div class="footer-content">
125
+ <div class="footer-left">
126
+ <p>&copy; 2025 PyTrade. All rights reserved.</p>
127
+ </div>
128
+ <div class="footer-center">
129
+ <ul class="footer-links">
130
+ <li><a href="/about">About Us</a></li>
131
+ <li><a href="/contact">Contact</a></li>
132
+ <li><a href="/privacy">Privacy Policy</a></li>
133
+ <li><a href="/terms">Terms & Conditions</a></li>
134
+ </ul>
135
+ </div>
136
+ <div class="footer-right">
137
+ <div class="social-media">
138
+ <a href="https://facebook.com" target="_blank" aria-label="Facebook"><i class="fab fa-facebook"></i></a>
139
+ <a href="https://twitter.com" target="_blank" aria-label="Twitter"><i class="fab fa-twitter"></i></a>
140
+ <a href="https://linkedin.com" target="_blank" aria-label="LinkedIn"><i class="fab fa-linkedin"></i></a>
141
+ <a href="https://instagram.com" target="_blank" aria-label="Instagram"><i class="fab fa-instagram"></i></a>
142
+ </div>
143
+ </div>
144
+ </div>
145
+ </footer>
146
+
147
+
148
+
149
+
src/app/homepage/homepage.scss ADDED
@@ -0,0 +1,217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Navigation Styles
2
+ .navigation-container {
3
+ background: linear-gradient(180deg, #0f0f0f, #0f0f0f00);
4
+ position: fixed;
5
+ width: 98%;
6
+ height: 10vw;
7
+ padding: 1vw;
8
+
9
+ .nav-content {
10
+ display: flex;
11
+ gap: 2vw;
12
+ align-items: center;
13
+ justify-content: space-between;
14
+
15
+ .logo-img {
16
+ width: 6vw;
17
+ height: 6vw;
18
+ border-radius: 50%;
19
+ box-shadow: 0 0 15px rgba(255, 255, 255, 0.8);
20
+ }
21
+
22
+ .logo-title {
23
+ font-size: 3vw;
24
+ }
25
+
26
+ .menu-item {
27
+ font-size: 1vw;
28
+ }
29
+
30
+ .user-avatar {
31
+ width: 2.5vw; /* Size of the avatar */
32
+ height: 2.5vw;
33
+ border-radius: 50%; /* Makes it circular */
34
+ overflow: hidden; /* Ensures image stays within circle */
35
+ display: inline-block;
36
+ position: relative;
37
+ background: linear-gradient(135deg, #38bdf8, #712d74); /* Gradient border */
38
+ padding: 3px; /* Space for gradient border */
39
+ align-self:flex-start
40
+ }
41
+
42
+ .user-avatar img {
43
+ width: 100%;
44
+ height: 100%;
45
+ border-radius: 50%; /* Keep image circular */
46
+ object-fit: cover; /* Cover the container without distortion */
47
+ }
48
+ }
49
+ }
50
+
51
+ // Homepage Styles
52
+ .homepage-container {
53
+ height: 48vw;
54
+ background: url('../../../public/final.png') no-repeat;
55
+ display: flex;
56
+ flex-direction: column;
57
+ justify-content: center;
58
+ align-items: center;
59
+
60
+ .py-title {
61
+ font-size: 4vw;
62
+ color: #fff;
63
+ }
64
+
65
+ .py-quote {
66
+ font-size: 1.5vw;
67
+ color: #fff;
68
+ }
69
+
70
+ .get-started-btn {
71
+ background: linear-gradient(90deg, #5af4fb, #712d74, #f134d0);
72
+ color: #fff;
73
+ padding: 10px 18px;
74
+ border-radius: 6px;
75
+ cursor: pointer;
76
+ font-weight: bold;
77
+ font-size: 1vw;
78
+ width: 8vw;
79
+ height: 3vw;
80
+ transition: all 0.3s ease-in-out;
81
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
82
+
83
+ &:hover {
84
+ transform: scale(1.05);
85
+ }
86
+ }
87
+ }
88
+
89
+ // Key Features Section
90
+ .key-feature-container {
91
+ background: url('../../../public/bgkey.png') no-repeat;
92
+ background-size: cover;
93
+ padding-left: 1vw;
94
+ text-align: center;
95
+ margin-top: -2vw;
96
+ padding-top: 2vw;
97
+ padding-bottom: 2vw;
98
+
99
+ h1 {
100
+ color: #fff;
101
+ font-size: 2vw;
102
+ }
103
+
104
+ .features {
105
+ display: grid;
106
+ grid-template-columns: repeat(3, 1fr);
107
+ gap: 40px;
108
+ max-width: 75vw;
109
+ margin: auto;
110
+
111
+ .feature-card {
112
+ background: #334155;
113
+ border-radius: 12px;
114
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
115
+ transition: transform 0.2s ease-in-out;
116
+ cursor: pointer;
117
+ color: #fff;
118
+ font-weight: bold;
119
+ font-size: 1vw;
120
+ display: flex;
121
+ flex-direction: column;
122
+ justify-content: center;
123
+ align-items: center;
124
+ gap: 1vw;
125
+ height: 13vw;
126
+
127
+ &:hover {
128
+ transform: scale(1.1);
129
+ }
130
+
131
+ span {
132
+ font-size: 2rem;
133
+ }
134
+
135
+ .feature-title {
136
+ color: #38bdf8;
137
+ }
138
+
139
+ .feature-detail {
140
+ padding: 1vw;
141
+ font-size: 0.8vw;
142
+ }
143
+ }
144
+ }
145
+ }
146
+
147
+ // Footer Styles
148
+ .footer {
149
+ background: linear-gradient(90deg, #38bdf8, #712d74); /* Gradient from blue to purple */
150
+ color: white;
151
+ padding: 20px 0;
152
+ text-align: center;
153
+ }
154
+
155
+ .footer-content {
156
+ display: flex;
157
+ justify-content: space-between;
158
+ align-items: center;
159
+ max-width: 1200px;
160
+ margin: 0 auto;
161
+ padding: 0 20px;
162
+ }
163
+
164
+ .footer-left p {
165
+ font-size: 1rem;
166
+ margin: 0;
167
+ }
168
+
169
+ .footer-center .footer-links {
170
+ list-style: none;
171
+ padding: 0;
172
+ }
173
+
174
+ .footer-center .footer-links li {
175
+ display: inline-block;
176
+ margin: 0 15px;
177
+ }
178
+
179
+ .footer-center .footer-links li a {
180
+ color: white;
181
+ text-decoration: none;
182
+ font-size: 1rem;
183
+ transition: color 0.3s ease;
184
+ }
185
+
186
+ .footer-center .footer-links li a:hover {
187
+ color: #f134d0; /* Accent color on hover */
188
+ }
189
+
190
+ .footer-right .social-media a {
191
+ color: white;
192
+ font-size: 1.5rem;
193
+ margin: 0 10px;
194
+ transition: color 0.3s ease;
195
+ }
196
+
197
+ .footer-right .social-media a:hover {
198
+ color: #f134d0; /* Accent color on hover */
199
+ }
200
+
201
+ @media screen and (max-width: 768px) {
202
+ .footer-content {
203
+ flex-direction: column;
204
+ text-align: center;
205
+ }
206
+
207
+ .footer-center {
208
+ margin-top: 20px;
209
+ }
210
+
211
+ .footer-left,
212
+ .footer-right {
213
+ margin-bottom: 20px;
214
+ }
215
+ }
216
+
217
+
src/app/homepage/homepage.spec.ts ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { Homepage } from './homepage';
4
+
5
+ describe('Homepage', () => {
6
+ let component: Homepage;
7
+ let fixture: ComponentFixture<Homepage>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ declarations: [Homepage]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(Homepage);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
src/app/homepage/homepage.ts ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Component, ElementRef } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'app-homepage',
5
+ standalone: false,
6
+ templateUrl: './homepage.html',
7
+ styleUrl: './homepage.scss'
8
+ })
9
+ export class Homepage {
10
+
11
+ constructor(private el: ElementRef) { }
12
+
13
+
14
+ ngAfterViewInit(): void {
15
+ const blocks: NodeListOf<HTMLElement> = this.el.nativeElement.querySelectorAll('.reveal');
16
+
17
+ if (!('IntersectionObserver' in window)) {
18
+ blocks.forEach(b => b.classList.add('in-view'));
19
+ return;
20
+ }
21
+
22
+ const io = new IntersectionObserver((entries) => {
23
+ entries.forEach(entry => {
24
+ if (entry.isIntersecting) {
25
+ entry.target.classList.remove('in-view');
26
+ void (entry.target as HTMLElement).offsetWidth; // force reflow
27
+ entry.target.classList.add('in-view');
28
+ }
29
+ });
30
+ }, { threshold: 0.3 });
31
+
32
+ blocks.forEach(b => io.observe(b));
33
+ }
34
+ }
src/app/marketselect/market.service.ts ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { HttpClient } from '@angular/common/http';
2
+ import { Injectable } from '@angular/core';
3
+ import { Observable } from 'rxjs';
4
+ import { of } from 'rxjs';
5
+ @Injectable({
6
+ providedIn: 'root'
7
+ })
8
+ export class MarketService {
9
+
10
+ private pyCompaniesApiUrl = 'http://127.0.0.1:5000/getcompanies';
11
+ private pyAnalyseApiUrl = 'http://127.0.0.1:5000/analysestock';
12
+ constructor(private http: HttpClient) { }
13
+
14
+ getCompanies(): Observable<any> {
15
+ return this.http.get<any>(this.pyCompaniesApiUrl);
16
+ }
17
+
18
+ getAnalyseResult(ticker: string[]): Observable<any> {
19
+ console.log(ticker)
20
+ return this.http.post<any>(this.pyAnalyseApiUrl, { ticker });
21
+ }
22
+
23
+
24
+ }
src/app/marketselect/marketselect.html ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="page">
2
+ <header class="header">
3
+ <div class="title">Market Selection</div>
4
+ <div class="subtitle">Choose Country → Exchange → Market, then pick Companies</div>
5
+ </header>
6
+
7
+ <section class="grid">
8
+ <!-- Filters -->
9
+ <div class="card">
10
+ <h3>Filters</h3>
11
+
12
+ <form [formGroup]="form" class="form">
13
+ <label>🌍 Country</label>
14
+ <select class="select" formControlName="country">
15
+ <option value="">-- Select Country --</option>
16
+ <option value="USA">USA</option>
17
+ <option value="India">India</option>
18
+ <option value="USA">Sweden</option>
19
+ <option value="USA">Germany</option>
20
+ </select>
21
+
22
+ <label>🏛️ Exchange</label>
23
+ <select class="select" formControlName="exchange" [disabled]="!exchanges.length">
24
+ <option value="">-- Select Exchange --</option>
25
+ <option *ngFor="let ex of exchanges" [value]="ex">{{ ex }}</option>
26
+ </select>
27
+
28
+ <label>📊 Market</label>
29
+ <select class="select" formControlName="market" [disabled]="!markets.length">
30
+ <option value="">-- Select Market --</option>
31
+ <option *ngFor="let m of markets" [value]="m">{{ m }}</option>
32
+ </select>
33
+
34
+ <button type="button" class="btn-primary" (click)="submit()">Run Analysis</button>
35
+ </form>
36
+ </div>
37
+
38
+ <!-- Companies -->
39
+ <div class="card">
40
+ <div class="companies-head">
41
+ <h3>Companies</h3>
42
+ <div class="badge">{{ (form.value.companies || []).length }}</div>
43
+ </div>
44
+
45
+ <div class="hint" *ngIf="!form.value.market">
46
+ Select a market to view the companies.
47
+ </div>
48
+
49
+ <div class="toolbar" *ngIf="form.value.market && companies.length">
50
+ <button class="btn-ghost" (click)="selectAll()">Select All</button>
51
+ <button class="btn-ghost" (click)="clearAll()" [disabled]="!(form.value.companies || []).length">Clear</button>
52
+ </div>
53
+
54
+ <div class="company-list" *ngIf="form.value.market && companies.length">
55
+ <label class="company"
56
+ *ngFor="let c of companies; trackBy: trackByName"
57
+ (click)="toggleCompany(c)"
58
+ [class.active]="isSelected(c)">
59
+ <span class="tick" aria-hidden="true">✔</span>
60
+ <span class="name">{{ c }}</span>
61
+ </label>
62
+ </div>
63
+
64
+ <div class="empty" *ngIf="form.value.market && !companies.length">
65
+ No companies available for this market.
66
+ </div>
67
+ </div>
68
+ </section>
69
+ </div>
70
+
71
+
72
+ <div class="overlay" *ngIf="loading">
73
+ <mat-spinner diameter="50"></mat-spinner>
74
+ <div class="hint">Processing…</div>
75
+ </div>
76
+
77
+
78
+
src/app/marketselect/marketselect.scss ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :host {
2
+ display: block;
3
+ }
4
+
5
+ .page {
6
+ min-height: 100vh;
7
+ padding: 32px 24px 48px;
8
+ background: linear-gradient(135deg, #0f172a, #1e293b);
9
+ color: #e2e8f0;
10
+ font-family: Arial, sans-serif;
11
+ }
12
+
13
+ .header {
14
+ max-width: 1200px;
15
+ margin: 0 auto 24px;
16
+ }
17
+
18
+ .title {
19
+ font-size: 28px;
20
+ font-weight: 700;
21
+ color: #38bdf8;
22
+ }
23
+
24
+ .subtitle {
25
+ color: #94a3b8;
26
+ margin-top: 4px;
27
+ }
28
+
29
+ .grid {
30
+ display: grid;
31
+ grid-template-columns: 1fr 1.3fr;
32
+ gap: 28px;
33
+ max-width: 1200px;
34
+ margin: 0 auto;
35
+ }
36
+
37
+ .card {
38
+ background: #1e293b;
39
+ border-radius: 14px;
40
+ box-shadow: 0 8px 20px rgba(0,0,0,.35);
41
+ padding: 22px;
42
+ }
43
+
44
+ h3 {
45
+ margin: 0 0 12px;
46
+ color: #e2e8f0;
47
+ }
48
+
49
+ .form label {
50
+ display: block;
51
+ margin: 14px 0 6px;
52
+ font-weight: 600;
53
+ color: #cbd5e1;
54
+ }
55
+
56
+ .select {
57
+ width: 100%;
58
+ background: #0f172a;
59
+ color: #e2e8f0;
60
+ border: 1px solid #334155;
61
+ border-radius: 8px;
62
+ padding: 10px 12px;
63
+ font-size: 14px;
64
+ outline: none;
65
+ transition: border-color .2s;
66
+ }
67
+
68
+ .select:focus {
69
+ border-color: #38bdf8;
70
+ }
71
+
72
+ .btn-primary {
73
+ margin-top: 18px;
74
+ width: 100%;
75
+ padding: 12px 14px;
76
+ font-size: 15px;
77
+ font-weight: 700;
78
+ background: linear-gradient(90deg, #4f46e5, #9333ea, #22c55e);
79
+ color: #fff;
80
+ border: 0;
81
+ border-radius: 10px;
82
+ cursor: pointer;
83
+ transition: opacity .15s;
84
+ }
85
+
86
+ .btn-primary:hover {
87
+ opacity: .9;
88
+ }
89
+
90
+ .companies-head {
91
+ display: flex;
92
+ align-items: center;
93
+ justify-content: space-between;
94
+ }
95
+
96
+ .badge {
97
+ background: #0ea5e9;
98
+ color: #0b1220;
99
+ border-radius: 999px;
100
+ padding: 4px 10px;
101
+ font-weight: 800;
102
+ font-size: 12px;
103
+ }
104
+
105
+ .hint {
106
+ margin-top: 8px;
107
+ color: #94a3b8;
108
+ font-size: 13px;
109
+ }
110
+
111
+ .toolbar {
112
+ display: flex;
113
+ gap: 8px;
114
+ margin: 10px 0 8px;
115
+ }
116
+
117
+ .btn-ghost {
118
+ background: #0f172a;
119
+ color: #e2e8f0;
120
+ border: 1px solid #334155;
121
+ border-radius: 8px;
122
+ padding: 8px 10px;
123
+ font-size: 13px;
124
+ cursor: pointer;
125
+ }
126
+
127
+ .btn-ghost:hover {
128
+ border-color: #38bdf8;
129
+ }
130
+
131
+ .company-list {
132
+ margin-top: 8px;
133
+ max-height: 320px;
134
+ overflow: auto;
135
+ border: 1px solid #334155;
136
+ border-radius: 10px;
137
+ padding: 8px;
138
+ background: #0f172a;
139
+ }
140
+
141
+ .company {
142
+ display: flex;
143
+ align-items: center;
144
+ gap: 10px;
145
+ padding: 10px 8px;
146
+ border-radius: 8px;
147
+ cursor: pointer;
148
+ border: 1px solid transparent;
149
+ transition: background .15s, border-color .15s;
150
+ user-select: none;
151
+ }
152
+
153
+ .company:hover {
154
+ background: #0b1220;
155
+ border-color: #1f2a44;
156
+ }
157
+
158
+ .company.active {
159
+ background: #0b1220;
160
+ border-color: #22c55e;
161
+ }
162
+
163
+ .company .tick {
164
+ opacity: 0;
165
+ font-size: 14px;
166
+ width: 16px;
167
+ }
168
+
169
+ .company.active .tick {
170
+ opacity: 1;
171
+ }
172
+
173
+ .company .name {
174
+ flex: 1;
175
+ }
176
+
177
+ .empty {
178
+ padding: 14px;
179
+ color: #94a3b8;
180
+ text-align: center;
181
+ }
182
+
183
+ @media (max-width: 960px) {
184
+ .grid {
185
+ grid-template-columns: 1fr;
186
+ }
187
+ }
188
+ .overlay {
189
+ position: fixed;
190
+ inset: 0;
191
+ display: grid;
192
+ place-items: center;
193
+ background: rgba(0,0,0,.45);
194
+ z-index: 1000;
195
+ color: #fff;
196
+ text-align: center;
197
+ }
198
+
199
+ .hint {
200
+ margin-top: 12px;
201
+ }
src/app/marketselect/marketselect.spec.ts ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { Marketselect } from './marketselect';
4
+
5
+ describe('Marketselect', () => {
6
+ let component: Marketselect;
7
+ let fixture: ComponentFixture<Marketselect>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ declarations: [Marketselect]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(Marketselect);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
src/app/marketselect/marketselect.ts ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Component, OnInit } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { FormBuilder, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
4
+ import { MarketService } from './market.service';
5
+ import { Router } from '@angular/router';
6
+ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
7
+ import { finalize } from 'rxjs';
8
+
9
+ type CountryKey = 'India' | 'USA';
10
+ type ExchangeKey = 'NSE' | 'BSE' | 'NYSE' | 'NASDAQ';
11
+
12
+ interface ExchangeData {
13
+ markets: string[];
14
+ marketCompanies: Record<string, string[]>; // market -> companies
15
+ }
16
+
17
+ const DATA: Record<CountryKey, Partial<Record<ExchangeKey, ExchangeData>>> = {
18
+ India: {
19
+ NSE: {
20
+ markets: ['Nifty50', 'Nifty100', 'Midcap', 'BankNifty'],
21
+ marketCompanies: {
22
+ Nifty50: ['Reliance Industries', 'TCS', 'Infosys', 'HDFC Bank', 'ICICI Bank', 'ITC', 'Bharti Airtel'],
23
+ Nifty100: ['L&T', 'Axis Bank', 'Kotak Mahindra Bank', 'Hindustan Unilever', 'Bajaj Finance', 'Wipro'],
24
+ Midcap: ['Crompton Greaves', 'Dixon Technologies', 'Deepak Nitrite', 'Astral', 'AU Small Finance Bank'],
25
+ BankNifty: ['HDFC Bank', 'ICICI Bank', 'Axis Bank', 'Kotak Mahindra Bank', 'SBI']
26
+ }
27
+ },
28
+ BSE: {
29
+ markets: ['Sensex', 'BSE 100', 'BSE 200', 'Midcap'],
30
+ marketCompanies: {
31
+ Sensex: ['Reliance Industries', 'TCS', 'Infosys', 'HDFC Bank', 'HCLTech', 'Tata Motors', 'NTPC'],
32
+ 'BSE 100': ['Mahindra & Mahindra', 'UltraTech Cement', 'Power Grid', 'Sun Pharma', 'Maruti Suzuki'],
33
+ 'BSE 200': ['Pidilite', 'Dabur', 'Divi’s Labs', 'Britannia', 'Grasim'],
34
+ Midcap: ['Voltas', 'BEL', 'Tata Power', 'Tata Elxsi', 'UBL']
35
+ }
36
+ }
37
+ },
38
+ USA: {
39
+ NYSE: {
40
+ markets: ['S&P 500', 'Dow Jones', 'Midcap', 'Sector ETFs'],
41
+ marketCompanies: {
42
+ 'S&P 500': ['Apple', 'Microsoft', 'NVIDIA', 'Amazon', 'Meta Platforms', 'Alphabet (A)'],
43
+ 'Dow Jones': ['Coca-Cola', 'Johnson & Johnson', 'Walmart', 'Chevron', 'Visa'],
44
+ Midcap: ['Ball Corp', 'Keysight', 'Fortinet', 'CrowdStrike', 'AMD'],
45
+ 'Sector ETFs': ['XLE', 'XLK', 'XLF', 'XLV', 'XLY']
46
+ }
47
+ },
48
+ NASDAQ: {
49
+ markets: ['NASDAQ 100', 'Growth', 'Midcap'],
50
+ marketCompanies: {
51
+ 'NASDAQ 100': ['Apple', 'Microsoft', 'NVIDIA', 'Amazon', 'Meta Platforms', 'Tesla', 'Adobe', 'Netflix'],
52
+ Growth: ['Snowflake', 'Datadog', 'ServiceNow', 'MongoDB', 'Cloudflare'],
53
+ Midcap: ['Zscaler', 'Okta', 'Trade Desk', 'Marvell Technology', 'On Semiconductor']
54
+ }
55
+ }
56
+ }
57
+ };
58
+
59
+ @Component({
60
+ selector: 'app-marketselect',
61
+ standalone: true,
62
+ imports: [CommonModule, ReactiveFormsModule, MatProgressSpinnerModule],
63
+ templateUrl: './marketselect.html',
64
+ styleUrls: ['./marketselect.scss']
65
+ })
66
+ export class MarketSelectComponent implements OnInit {
67
+ form: FormGroup;
68
+ loading = false;
69
+ exchanges: ExchangeKey[] = [];
70
+ markets: string[] = [];
71
+ companies: string[] = []; // populated only after market selection
72
+ selectedCompanies: string[] = [];
73
+ constructor(private fb: FormBuilder, private marketService: MarketService, private router:Router) {
74
+ this.form = this.fb.group({
75
+ country: new FormControl<CountryKey | ''>(''),
76
+ exchange: new FormControl<ExchangeKey | ''>(''),
77
+ market: new FormControl<string | ''>(''),
78
+ companies: this.fb.control<string[]>([])
79
+ });
80
+ }
81
+
82
+ ngOnInit(): void {
83
+
84
+ this.marketService.getCompanies()
85
+ .subscribe({
86
+ next: res => {
87
+ console.log(res);
88
+ },
89
+ error: err => {
90
+ console.error('API error:', err);
91
+ }
92
+ });
93
+
94
+ // Country change: reset and load exchanges
95
+ this.form.get('country')!.valueChanges.subscribe((country) => {
96
+ this.form.patchValue({ exchange: '', market: '', companies: [] }, { emitEvent: false });
97
+ this.exchanges = this.getExchanges(country as CountryKey | '');
98
+ this.markets = [];
99
+ this.companies = [];
100
+ });
101
+
102
+ // Exchange change: reset and load markets
103
+ this.form.get('exchange')!.valueChanges.subscribe((exchange) => {
104
+ const country = this.form.value.country as CountryKey | '';
105
+ this.form.patchValue({ market: '', companies: [] }, { emitEvent: false });
106
+ this.markets = this.getMarkets(country, exchange as ExchangeKey | '');
107
+ this.companies = [];
108
+ });
109
+
110
+ // Market change: load companies for that market
111
+ this.form.get('market')!.valueChanges.subscribe((market) => {
112
+ const country = this.form.value.country as CountryKey | '';
113
+ const exchange = this.form.value.exchange as ExchangeKey | '';
114
+ this.form.patchValue({ companies: [] }, { emitEvent: false });
115
+ this.companies = this.getCompanies(country, exchange, (market || '') as string);
116
+ });
117
+ }
118
+
119
+ // Helpers
120
+ private getExchanges(country: CountryKey | ''): ExchangeKey[] {
121
+ if (!country) return [];
122
+ return Object.keys(DATA[country] || {}) as ExchangeKey[];
123
+ }
124
+
125
+ private getMarkets(country: CountryKey | '', exchange: ExchangeKey | ''): string[] {
126
+ if (!country || !exchange) return [];
127
+ return DATA[country]?.[exchange]?.markets ?? [];
128
+ }
129
+
130
+ private getCompanies(country: CountryKey | '', exchange: ExchangeKey | '', market: string): string[] {
131
+ if (!country || !exchange || !market) return [];
132
+ return DATA[country]?.[exchange]?.marketCompanies?.[market] ?? [];
133
+ }
134
+
135
+ // Company selection
136
+ isSelected(name: string): boolean {
137
+ const selected = this.form.value.companies ?? [];
138
+ return selected.includes(name);
139
+ }
140
+ toggleCompany(name: string): void {
141
+ const set = new Set(this.form.value.companies ?? []);
142
+ set.has(name) ? set.delete(name) : set.add(name);
143
+ this.form.patchValue({ companies: Array.from(set) });
144
+ }
145
+ selectAll(): void {
146
+ this.form.patchValue({ companies: this.companies.slice() });
147
+ }
148
+ clearAll(): void {
149
+ this.form.patchValue({ companies: [] });
150
+ }
151
+
152
+ submit(): void {
153
+ this.loading = true;
154
+ this.selectedCompanies = ['TCS.NS', 'ICICIBANK.NS']
155
+ this.marketService.getAnalyseResult(this.selectedCompanies)
156
+ .pipe(finalize(() => this.loading = false))
157
+ .subscribe({
158
+ next: res => {
159
+ // navigate AFTER data is returned; pass the value
160
+ console.log(res);
161
+ this.router.navigate(['/analysepage'], { state: { result: res } });
162
+ },
163
+ error: err => {
164
+ console.error('API error:', err);
165
+ // you can add MatSnackBar here if needed
166
+ }
167
+ });
168
+ }
169
+
170
+
171
+
172
+ trackByName = (_: number, name: string) => name;
173
+ }
src/app/screenerpage/screenerpage.css ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ body {
2
+ background-color: #0f172a;
3
+ color: #e2e8f0;
4
+ font-family: Arial, sans-serif;
5
+ margin: 0;
6
+ padding: 20px;
7
+ }
8
+
9
+ h1, h2 {
10
+ text-align: center;
11
+ color: #38bdf8;
12
+ margin-bottom: 20px;
13
+ }
14
+
15
+ .dashboard {
16
+ display: grid;
17
+ grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
18
+ gap: 25px;
19
+ }
20
+
21
+ .card {
22
+ background: #1e293b;
23
+ border-radius: 12px;
24
+ padding: 20px;
25
+ box-shadow: 0 4px 12px rgba(0,0,0,0.4);
26
+ }
27
+
28
+ .card h2 {
29
+ margin-bottom: 15px;
30
+ font-size: 1.2rem;
31
+ color: #38bdf8;
32
+ }
33
+
34
+ table {
35
+ width: 100%;
36
+ border-collapse: collapse;
37
+ margin-top: 10px;
38
+ }
39
+
40
+ table th, table td {
41
+ border-bottom: 1px solid #334155;
42
+ padding: 8px;
43
+ text-align: left;
44
+ }
45
+
46
+ table th {
47
+ color: #38bdf8;
48
+ }
49
+
50
+ .big-table {
51
+ margin-top: 40px;
52
+ background: #1e293b;
53
+ padding: 20px;
54
+ border-radius: 12px;
55
+ }
56
+
57
+ .main {
58
+ flex: 1;
59
+ display: flex;
60
+ flex-direction: column;
61
+ padding: 20px;
62
+ gap: 20px;
63
+ overflow-y: auto;
64
+ }
65
+
66
+ .breadcrumb {
67
+ display: flex;
68
+ align-items: center;
69
+ font-size: 0.95em;
70
+ color: #94a3b8;
71
+ margin-bottom: -10px;
72
+ font-size: 16px;
73
+ }
74
+
75
+ .breadcrumb a {
76
+ color: #38bdf8;
77
+ text-decoration: none;
78
+ margin-right: 5px;
79
+ }
80
+
81
+ .breadcrumb span {
82
+ margin: 0 5px;
83
+ }