웹스쿨

C# 주식분석 프로그램 처녀작품 본문

개인 프로젝트/C# 키움 주식 패턴 분석

C# 주식분석 프로그램 처녀작품

마스터욱 2023. 3. 30. 01:52
반응형

C# 을 처음 공부하게 된 계기가 된 개인 프로젝트

엄청난 구글링과 디버깅과 빨간 밑줄로 인해 나의 내공은 강해졌고, 결국 완성도 못한채 ㅄ 딴따라가 된 나의 C# 처녀작이다. 헤헤

C# 스승을 한분 두고싶다...

문법은 JAVA 랑 거의 흡사하지만 역시나 PHP 보다는 깐깐하다. PHP만세

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using System.Timers;
 
namespace Stock
{
    public partial class Form1 : Form
    {
        //==============================================================================//
 
        //종목별 모든 row 데이터를 저장하는 클래스
        private class StockData
        {
            public string 종목코드;
            public string 종목이름;
 
            //종목의 Row 값을 모두 저장한다.
            //ex) 종목레코드['레코드_고유번호'] = StockRec 데이터
            public Dictionary<int, StockRec> 종목레코드 = new Dictionary<int, StockRec>(); //string(레코드 고유번호), StockRec(로우정보)
 
            //체결량별 데이터를 묶음.
            //인덱스는 레코드의 고유번호이다.
            //ex) 체결량별_인덱스['100']['레코드_고유번호'] = StockRec 데이터
            public Dictionary<intDictionary<int, StockRec>> 체결량별_인덱스 = new Dictionary<intDictionary<int, StockRec>>();
 
            //string value 값 - 레코드_고유번호
            //string value 값 - 규칙성존재함(해당시간에 데이터가 존재하고 규칙성까지 존재함.)
            //인덱스는 레코드의 체결시간이다.(해당 체결시간에 데이터가 존재하는지의 유무를 확인하기 위해 만듬)
            //ex) 체결량별_타임['100'][HHiiss_Mktime] = 레코드_고유번호 or "규칙성존재함";
            public Dictionary<intDictionary<stringstring>> 체결량별_타임 = new Dictionary<intDictionary<stringstring>>();
 
            //ex) 체결량별_규칙분석['100']['00060'] = StockRec; => 100개 체결이 60초 간격으로 존재하는 데이터를 넣음.
            public Dictionary<intDictionary<string, ArrayList>> 체결량별_규칙분석 = new Dictionary<intDictionary<string, ArrayList>>();
 
            //ex) 체결량별_순위분석['100'] = 5회 규칙이상인 체결건 기준으로 (체결량 * 체결금액) 의 총합
            public Dictionary<intint> 체결량별_순위분석 = new Dictionary<intint>();
 
            private SimpleLogger logger = new SimpleLogger();
 
            //Stock 의 레코드 정보를 담아둘 구조체
            //private StockRec SR;
            public class StockRec
            {
                public string HHiiss;
                public int 체결량;
                public int 체결가;
                public int 레코드_고유번호;
                public string 규칙인터벌; //5자리 초단위 숫자(ex : 00060, 00120)
            }
 
            //규칙분석 데이터 만들기
            public void SetStockAna()
            {
                Dictionary<intDictionary<string, ArrayList>> 체결량별_규칙분석_임시 = new Dictionary<intDictionary<string, ArrayList>>();
                foreach (KeyValuePair<int, StockRec> row in 종목레코드)
                {
                    int 체결량 = row.Value.체결량;
                    string 규칙성 = row.Value.규칙인터벌; //5자리 초단위 string
                    if (규칙성 == "")
                    {
                        //규칙성이 없는 자료는 굳이 보여줄 필요 없징
                        continue;
                    }
 
                    if (!체결량별_규칙분석_임시.ContainsKey(체결량))
                    {
                        체결량별_규칙분석_임시[체결량] = new Dictionary<string, ArrayList>();
                    }
 
                    if (!체결량별_규칙분석_임시[체결량].ContainsKey(규칙성))
                    {
                        체결량별_규칙분석_임시[체결량][규칙성] = new ArrayList();
                    }
 
                    체결량별_규칙분석_임시[체결량][규칙성].Add(row.Value);
                }
 
                var TEMP = from entry in 체결량별_규칙분석_임시 orderby entry.Key descending select entry;
                //Dictionary<int, Dictionary<string, ArrayList>> 체결량별_규칙분석 = new Dictionary<int, Dictionary<string, ArrayList>>();
                foreach (KeyValuePair<intDictionary<string, ArrayList>> row in TEMP)
                {
                    //체결량별_규칙분석[row.Key] = 체결량별_규칙분석_임시[row.Key]; //call by reference
                    //체결량별_규칙분석[row.Key] = new Dictionary<string, ArrayList>(체결량별_규칙분석_임시[row.Key]); //call by value
 
                    int 체결량 = row.Key;
                    체결량별_규칙분석[체결량] = new Dictionary<string, ArrayList>();
 
                    foreach (KeyValuePair<string, ArrayList> cp_row in row.Value) // call by value
                    {
                        ArrayList StockRecList = new ArrayList(cp_row.Value);
                        string 규칙성 = cp_row.Key;
 
                        체결량별_규칙분석[체결량][규칙성] = new ArrayList();
                        foreach (StockRec StockRow in StockRecList)
                        {
                            체결량별_규칙분석[체결량][규칙성].Add(StockRow);
                        }
                    }
                }
 
                //같은체결량 안에서 구간(초단위 시간)이 -1,+1 구간이 겹치는 데이터를 합치자.
                /*
                foreach (KeyValuePair<int, Dictionary<string, ArrayList>> 임시로우 in 체결량별_규칙분석_임시)
                {
                    int 체결량 = 임시로우.Key;
                    foreach (KeyValuePair<string, ArrayList> 임시로우2 in 임시로우.Value) //동일체결량
                    {
                        int second = int.Parse(임시로우2.Key); //인터벌 초단위 6자리
                        int start = second - 범위조정_체결시간;
                        int end = second - 범위조정_체결시간;
                        for(int i = start; i <= end; i++)
                        {
                            string 규칙성_초단위 = Regex.Replace(i.ToString(), @"\d+", n => n.Value.PadLeft(5, '0'));
                            if(체결량별_규칙분석[체결량].ContainsKey(규칙성_초단위) && 체결량별_규칙분석[체결량].ContainsKey(임시로우2.Key))
                            {
                                //체결량별_규칙분석[체결량][row2.Key] 와 체결량별_규칙분석[체결량][i] 를 합치고 체결량별_규칙분석[체결량][i] 를 제거하자.
                                foreach(StockRec row3 in 체결량별_규칙분석[체결량][규칙성_초단위])
                                {
                                    체결량별_규칙분석[체결량][임시로우2.Key].Add(row3);
                                }
                                체결량별_규칙분석[체결량].Remove(규칙성_초단위);
                            }
                        }
                    }
                }
                */
 
 
                //다른 체결량과 비교하면서 체결량이 -1,+1 차이 범위안이고 시간(초단위)데이터도 -1,+1 차이 범위안이면 합치자.
                /*
                체결량별_규칙분석_임시 = new Dictionary<int, Dictionary<string, ArrayList>>();
                foreach (KeyValuePair<int, Dictionary<string, ArrayList>> row in 체결량별_규칙분석) // call by value 복사
                {
                    int 체결량 = row.Key;
                    foreach (KeyValuePair<string, ArrayList> cp_row in row.Value) // call by value
                    {
                        ArrayList StockRecList = new ArrayList(cp_row.Value);
                        string 규칙성 = cp_row.Key;
                        체결량별_규칙분석_임시[체결량] = new Dictionary<string, ArrayList>();
                        체결량별_규칙분석_임시[체결량][규칙성] = StockRecList;
                    }
                }
                foreach (KeyValuePair<int, Dictionary<string, ArrayList>> 임시로우 in 체결량별_규칙분석_임시)
                {
                    int 체결량 = 임시로우.Key;
                    int start = 체결량 - 범위조정_체결량;
                    int end = 체결량 + 범위조정_체결량;
                    for(int i = start; i <= end; i++)
                    {
                        //public Dictionary<int, Dictionary<string, ArrayList>> 체결량별_규칙분석 = new Dictionary<int, Dictionary<string, ArrayList>>();
                        //체결량별_규칙분석[100]['00060'] = StockRec; => 100개 체결이 60초 간격으로 존재하는 데이터를 넣음.
                        if(체결량별_규칙분석.ContainsKey(i))
                        {
                            int 근접한_체결량 = i;
                            foreach(KeyValuePair<string, ArrayList> 로우1 in 임시로우.Value) //체결량 '100'의 row 들의 루프
                            {
                                if(!체결량별_규칙분석[체결량].ContainsKey(로우1.Key)) //로우1.Key => 규칙성 5자리
                                {
                                    continue;
                                }
                                int 규칙성1 = int.Parse(로우1.Key);
                                int 시작 = 규칙성1 - 범위조정_체결시간;
                                int 종료 = 규칙성1 + 범위조정_체결시간;
                                //체결량별_규칙분석[101]['00061'] = StockRec; => 101개 체결이 61초 간격으로 존재하는 데이터를 넣음.
                                if (체결량별_규칙분석.ContainsKey(근접한_체결량))
                                {
                                    foreach (KeyValuePair<string, ArrayList> 로우2 in 체결량별_규칙분석_임시[근접한_체결량]) //체결량 '101'의 row 들의 루프
                                    {
                                        if(!체결량별_규칙분석[근접한_체결량].ContainsKey(로우2.Key)) //로우2.Key => 규칙성 5자리
                                        {
                                            continue;
                                        }
                                        //초단위가 -1,+1 사이에 있는지 확인
                                        int 규칙성2 = int.Parse(로우2.Key);
                                        if (시작 <= 규칙성2 && 규칙성2 <= 종료)
                                        {
                                            //MessageBox.Show("합치기 체결량의 규칙성 = " + 체결량 + " : " + 로우1.Key);
                                            //MessageBox.Show(로우2.Value.Count.ToString());
                                            //합치자
                                            foreach (StockRec 레코드 in 로우2.Value)
                                            {
                                                //MessageBox.Show("로우1.Key = " + 로우1.Key);
                                                체결량별_규칙분석[체결량][로우1.Key].Add(레코드);
                                            }
                                            //합쳤으니 뒤에껀 지우자
                                            체결량별_규칙분석[근접한_체결량].Remove(로우2.Key);
                                            //MessageBox.Show("삭제된 체결량의 규칙성 = " + 근접한_체결량 + " : " + 로우2.Key);
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                */
 
                //ex) 체결량별_규칙분석['100']['00060'] = StockRec; => 100개 체결이 60초 간격으로 존재하는 데이터를 넣음.
                foreach (KeyValuePair<intDictionary<string, ArrayList>> 키_체결량 in 체결량별_규칙분석)
                {
                    //ex) 체결량별_순위분석['100'] = 5회 규칙이상인 체결건 기준으로 (체결량 * 체결금액) 의 총합
                    int 체결량 = 키_체결량.Key;
                    if (체결량 < 0//일단 마이너스는 배재하자.
                    {
                        //continue;
                    }
 
                    int SecondPrice = 0;
                    foreach (KeyValuePair<string, ArrayList> 키_규칙인터벌 in 키_체결량.Value) //체결량이 같은 체결건들을 모아놓음
                    {
                        if (키_규칙인터벌.Value.Count >= 규칙성기준) //규칙성이 5회 이상인 거래건에 한해서 합을 더하자.
                        {
                            int 규칙인터벌 = int.Parse(키_규칙인터벌.Key);
                            int Sum = 0;
                            foreach (StockRec 한줄_레코드 in 키_규칙인터벌.Value) //규칙인터벌이 동일한 리스트
                            {
                                Sum += 한줄_레코드.체결가;
                            }
                            int SumAvr = Sum / 키_규칙인터벌.Value.Count; //평균체결가
 
                            //초당 금액을 구하자.
                            SecondPrice += SumAvr * 체결량 / 규칙인터벌;
                        }
                    }
 
                    if (SecondPrice != 0)
                    {
                        체결량별_순위분석[체결량] = SecondPrice;
                    }
                }
            }
 
            //종목데이터에 Row 삽입.
            public void SetStockRec(int 레코드_고유번호, string HHiiss, int 체결량, int 체결가)
            {
                StockRec SR = new StockRec();
                SR.HHiiss = HHiiss;
                SR.체결량 = 체결량;
                SR.체결가 = 체결가;
                SR.레코드_고유번호 = 레코드_고유번호;
                SR.규칙인터벌 = "";
                종목레코드[레코드_고유번호] = SR;
            }
 
            //체결량별로 시간데이터를 쌓자.
            public Dictionary<intDictionary<int, StockRec>> GetStockData()
            {
                if (체결량별_인덱스.Count > 0)
                {
                    return 체결량별_인덱스;
                }
 
                Dictionary<intDictionary<int, StockRec>> List = new Dictionary<intDictionary<int, StockRec>>();
                foreach (KeyValuePair<int, StockRec> row in 종목레코드)
                {
                    int 체결량 = row.Value.체결량;
                    int 레코드_고유번호 = row.Value.레코드_고유번호;
 
                    if (!List.ContainsKey(체결량))
                    {
                        List[체결량] = new Dictionary<int, StockRec>();
                        체결량별_타임[체결량] = new Dictionary<stringstring>();
                    }
 
                    List[체결량][레코드_고유번호] = row.Value;
                    체결량별_타임[체결량][GetMktime(row.Value.HHiiss).ToString()] = 레코드_고유번호.ToString();
                }
 
                //체결량 오림차순 정렬
                var ListSort = List.Keys.ToList();
                ListSort.Sort();
                foreach (var key in ListSort)
                {
                    체결량별_인덱스[key] = List[key];
                }
 
                return 체결량별_인덱스;
            }
        }
        private Dictionary<string, StockData> 전체종목데이터 = new Dictionary<string, StockData>();
        private Dictionary<stringfloat> 순위분석 = new Dictionary<stringfloat>(); //최종분석결과
        private string 현재클릭종목;
        private string 레코드_마지막_HHiiss;
        private int 레코드_라스트_번호;
        private static int 규칙성기준 = 5//5카운트 이상의 규칙성만 인정한다.
        private static int 범위조정_체결시간 = 1//-1, +1 범위 => 이건 시간범위조정임(초단위)
        private static int 범위조정_체결량 = 1//-1,+1 범위 => 이건 체결량범위조정임(건단위)
 
        private System.Windows.Forms.Timer 타이머 = new System.Windows.Forms.Timer();
        private int 타이머카운트 = 0;
        private bool 모든종목분석 = false;
        private int CodeListAutoNumber = 0//모든종목분석 순서
        private static Dictionary<stringstring> 코드번호_To_시가총액 = new Dictionary<stringstring>();
        private bool 분석중인지 = false;
 
        //==============================================================================//
 
        private string LoginName;
 
        private Dictionary<stringstring> CodeToStockName = new Dictionary<stringstring>(); //코드번호와 코드네임을 담을 변수
        private Dictionary<intstring> CodeList = new Dictionary<intstring>(); //모든종목분석을 위한 코드번호를 담을 어레이리스트
        private int GatherTime = 30//최근 x분동안의 체결정보만 수집한다.(전체수집에 한해서)
        private int GatherStartTime; //정보수집 Start 시간
        private int TestCodeCount = 10//테스트할때 TestCodeCount 개수의 종목만 수집한다.
 
        private int LoginInterval = 10000//종목 호출 횟수가 255개로 제한되어 있기 때문에 중간에 세션변경 => 이거 안되는 거임...
        private string LoginType = ""//타입이 SESSION이 되면 종목다시 호출시작~, 최초로그인은 타입이 START 임.
 
        private SimpleLogger logger = new SimpleLogger();
 
        public Form1()
        {
            InitializeComponent();
 
            textBoxLoginInfo.Text = "Open API START" + Environment.NewLine;
            axKHOpenAPI1.Visible = false;
 
            logger.RemoveLog();
 
            /*
            Dictionary<string, Dictionary<string, string>> test = new Dictionary<string, Dictionary<string, string>>();
            test["100"] = new Dictionary<string, string>();
            test["100"]["100_"] = "100_value";
            Dictionary<string, Dictionary<string, string>> test2 = new Dictionary<string, Dictionary<string, string>>(test);
            test["100"]["100_"] = "100_value_re";
            MessageBox.Show(test2["100"]["100_"]);
            */
        }
 
        //주식종목리스트에서 주식 row를 클릭하면 실행
        private void listBoxStock_SelectedIndexChanged(object sender, EventArgs e)
        {
            //161028 어차피 모든종목분석만 할거기 때문에 주석처리함.
            /*
            string listBoxText = this.listBoxStock.Items[this.listBoxStock.SelectedIndex].ToString();
            string[] tmp = listBoxText.Split('(');
            string CodeName = tmp[0].Trim();
            string CodeNumber = tmp[1].Replace(")", string.Empty).Trim();
            textBoxLoginInfo.Text = "";
            dataGridView1.Rows.Clear();
            string obj_data = CodeNumber;
            listBoxStock_SelectedIndexChanged_Func(obj_data);
            */
        }
 
        private void listBoxStock_SelectedIndexChanged_Func(string data)
        {
            /*
            if (CodeListAutoNumber != 0 && CodeListAutoNumber % LoginInterval == 0)
            {
                button1_Click_Func("SESSION"); //재로그인
                return;
            }
            */
 
            LogBox.Text += CodeToStockName[CodeList[CodeListAutoNumber]] + " 분석시작!" + Environment.NewLine;
 
            현재클릭종목 = data;
            //MessageBox.Show(현재클릭종목);
 
            dataGridView1.Rows.Clear();
 
            //===========================================//
            StockData 종목데이터 = new StockData();
            종목데이터.종목코드 = 현재클릭종목;
            종목데이터.종목이름 = CodeToStockName[현재클릭종목];
            //MessageBox.Show(종목데이터.종목이름);
            전체종목데이터[현재클릭종목] = 종목데이터;
 
            레코드_라스트_번호 = 0;
            레코드_마지막_HHiiss = "";
            타이머카운트 = 0;
            //===========================================//
 
            //일단 기본정보부터 가져오자. 시가총액을 알아내기 위해서~
            //axKHOpenAPI1.SetInputValue("종목코드", 현재클릭종목);
            //axKHOpenAPI1.CommRqData(현재클릭종목 + "_체결정보요청", "opt10003", 0, "0101"); //스레드 구조체값을 구분하기 위해 CodeNumber 값을 넘긴다.
 
            axKHOpenAPI1.SetInputValue("종목코드", 현재클릭종목);
            axKHOpenAPI1.CommRqData(현재클릭종목 + "_주식기본정보""opt10001"0"0101");
        }
 
        //실시간 시세 이벤트라는데 뭔지 잘 몰겠다.
        //이게 보니깐 주기적으로 호출이 된다... 아마도 특정초단위로 알아서 호출되는 건가보다...
        private void axKHOpenAPI1_OnReceiveRealData(object sender, AxKHOpenAPILib._DKHOpenAPIEvents_OnReceiveRealDataEvent e)
        {
            //textBoxLoginInfo.Text = "axKHOpenAPI1_OnReceiveRealData : " + e.sRealData + Environment.NewLine;
        }
 
        private void axKHOpenAPI1_OnReceiveTrData(object sender, AxKHOpenAPILib._DKHOpenAPIEvents_OnReceiveTrDataEvent e)
        {
            string[] tmp = e.sRQName.Split('_');
            string CodeNumber = tmp[0];
            string sRQName = tmp[1];
 
            //MessageBox.Show(e.sPrevNext);
 
            타이머카운트++;
 
            if (sRQName == "주식기본정보")
            {
                /*
                content += "종목명 : " + axKHOpenAPI1.CommGetData(e.sTrCode, "", e.sRQName, 0, "종목명").Trim() + Environment.NewLine;
                content += "등락율 : " + axKHOpenAPI1.CommGetData(e.sTrCode, "", e.sRQName, 0, "등락율").Trim() + Environment.NewLine;
                content += "거래량 : " + axKHOpenAPI1.CommGetData(e.sTrCode, "", e.sRQName, 0, "거래량").Trim() + Environment.NewLine;
                content += "시가 : " + axKHOpenAPI1.CommGetData(e.sTrCode, "", e.sRQName, 0, "시가").Trim() + Environment.NewLine;
                content += "고가 : " + axKHOpenAPI1.CommGetData(e.sTrCode, "", e.sRQName, 0, "고가").Trim() + Environment.NewLine;
                content += "저가 : " + axKHOpenAPI1.CommGetData(e.sTrCode, "", e.sRQName, 0, "저가").Trim() + Environment.NewLine;
                MessageBox.Show(content);
                */
 
 
                //각 종목별로 시가총액을 저장하자.
                string 시가총액 = axKHOpenAPI1.CommGetData(e.sTrCode, "", e.sRQName, 0"시가총액").Trim();
                //LogBox.Text += CodeToStockName[CodeNumber] + " => " + 시가총액 + Environment.NewLine;
                코드번호_To_시가총액[CodeNumber] = 시가총액; //시가총액은 단위가 (억)임.
 
                axKHOpenAPI1.SetInputValue("종목코드", 현재클릭종목);
                axKHOpenAPI1.CommRqData(현재클릭종목 + "_체결정보요청""opt10003"0"0101"); //스레드 구조체값을 구분하기 위해 CodeNumber 값을 넘긴다.
            }
            else if (sRQName == "체결정보요청")
            {
                //dataGridView1.Rows.Clear();
                int cnt = axKHOpenAPI1.GetRepeatCnt(e.sTrCode, e.sRQName);
                textBoxLoginInfo.Text = "";
                textBoxLoginInfo.Text += Environment.NewLine;
                textBoxLoginInfo.Text += " -> 전체  : " + CodeToStockName.Count + " / 현재 : " + CodeListAutoNumber + "개 완료" + Environment.NewLine;
                textBoxLoginInfo.Text += Environment.NewLine;
                textBoxLoginInfo.Text += " -> 종목  : " + CodeToStockName[현재클릭종목] + Environment.NewLine;
                textBoxLoginInfo.Text += " -> 전체  : " + 레코드_라스트_번호 + Environment.NewLine;
                textBoxLoginInfo.Text += " -> 호출  : " + 타이머카운트 + Environment.NewLine;
                textBoxLoginInfo.Text += " -> LAST  : " + 레코드_마지막_HHiiss + Environment.NewLine;
                textBoxLoginInfo.Text += Environment.NewLine;
 
                bool IsEnd = false;
                for (int i = 0; i < cnt; i++)
                {
                    //시간, 현재가, 전일대비, 대비율, 우선매도호가단위, 우선매수호가단위, 체결거래량, sign, 누적거래량, 누적거래대금, 체결강도
                    string 체결거래량 = axKHOpenAPI1.CommGetData(e.sTrCode, "", e.sRQName, i, "체결거래량").ToString().Trim();
                    string 체결시간 = axKHOpenAPI1.CommGetData(e.sTrCode, "", e.sRQName, i, "시간").ToString().Trim();
                    string 현재가 = axKHOpenAPI1.CommGetData(e.sTrCode, "", e.sRQName, i, "현재가").ToString().Trim();
                    현재가 = 현재가.Replace("-"""); // 마이너스 제거
 
                    if (체결거래량 != "")
                    {
                        string[] data = {
                            레코드_라스트_번호.ToString(),
                            체결거래량,
                            체결시간,
                            현재가,
                            "같은거보기"
                        };
 
                        //===========================================================//
                        //종목데이터에 Row 자료를 담는다.
                        //MessageBox.Show(현재클릭종목);
                        StockData 종목데이터 = 전체종목데이터[현재클릭종목];
                        /*
                        LogBox.Text += Environment.NewLine;
                        LogBox.Text += " -> 레코드_라스트_번호 = " + 레코드_라스트_번호;
                        LogBox.Text += " -> 체결시간 = " + 체결시간;
                        LogBox.Text += " -> 체결거래량 = " + 체결거래량;
                        LogBox.Text += " -> 현재가 = " + 현재가;
                        LogBox.Text += Environment.NewLine;
                        */
                        종목데이터.SetStockRec(레코드_라스트_번호, 체결시간, int.Parse(체결거래량), int.Parse(현재가)); //따로 소팅할 필요도 없겠지 헤헤
                        레코드_라스트_번호++;
                        레코드_마지막_HHiiss = 체결시간;
                        //===========================================================//
 
 
                        dataGridView1.Rows.Add(data);
                        //해쉬데이터입력(체결거래량, 체결시간, thread_info);
 
                        if (모든종목분석 == true)
                        {
                            if (GetMktime(체결시간) < (GatherStartTime - (60 * GatherTime))) //수집시작시점을 기준으로 GatherTime(분)이 지난 데이터는 필요없다.
                            {
                                //LogBox.Text += GetMktime(체결시간) + " > " + (DateTime.Now.ToString("HHmmss")) + Environment.NewLine;
                                IsEnd = true;
                                break;
                            }
                        }
                    }
                }
 
                //30 * 10 = 300 rows 가 넘어서면 중지하자.
                if (e.sPrevNext == "2" && IsEnd == false)
                {
                    //5번 호출후에는 1초의 인터벌후에 호출해야 됨.                    
                    if (타이머카운트 % == 0)
                    {
                        textBoxLoginInfo.Text += "타이머 호출("+ (타이머카운트 / 5+ ")" + Environment.NewLine;
 
                        //아귀먼트 전달을 위해 아래 타이머로 교체
                        //System.Threading.Timer timer = new System.Threading.Timer(timerHandler, thread_info.NowNum, 0, 2000);
 
                        타이머.Interval = 1000//100 => 0.1 second
                        타이머.Tick += new EventHandler(timerHandler);
                        타이머.Start(); //The countdown is launched!
                    }
                    else
                    {
                        //textBoxLoginInfo.Text += "연속호출("+ thread_info.ClickCodeNumber + ")" + Environment.NewLine;
                        axKHOpenAPI1.SetInputValue("종목코드", 현재클릭종목);
                        axKHOpenAPI1.CommRqData(현재클릭종목 + "_체결정보요청""opt10003"2"0101");
                    }
                }
                else if (!전체종목데이터.ContainsKey(현재클릭종목))
                {
                    MessageBox.Show(현재클릭종목 + " 데이터가 없습니다.");
                }
                else
                {
                    textBoxLoginInfo.Text = "================= 데이터(" + 현재클릭종목 + ") 수집 끝 ================" + Environment.NewLine;
 
                    //=======================================================//
                    //StockData 에 값이 제대로 들어갔는지 확인.
                    //MessageBox.Show(현재클릭종목);
                    StockData 종목데이터 = 전체종목데이터[현재클릭종목];
 
                    //"종목데이터.체결량별_타임"도 같이 생성함.
                    Dictionary<intDictionary<int, StockData.StockRec>> 체결량별_인덱스 = 종목데이터.GetStockData();
 
                    textBoxLoginInfo.Text += 현재클릭종목 + " 수집완료!" + Environment.NewLine;
                    if (체결량별_인덱스.Count < 1)
                    {
                        textBoxLoginInfo.Text += "데이터가 없습니다!";
                    }
                    else
                    {
                        /*
                         * public Dictionary<int, Dictionary<int, StockRec>> 체결량별_인덱스 = new Dictionary<int, Dictionary<int, StockRec>>();
                         * 체결량별_인덱스[100] = 체결량이 '100'인 StockRec 데이터 리스트
                         * 체결량별_인덱스[105] = 체결량이 '105'인 StockRec 데이터 리스트
                         * ...
                         * ..
                         * .
                         */
                        foreach (KeyValuePair<intDictionary<int, StockData.StockRec>> 체결량별_인덱스_배열 in 체결량별_인덱스)
                        {
                            //지금부터 주석의 예시는 체결량이 '100' 일경우로 가정한다.
 
                            /*
                             * 체결량별_인덱스_배열[레코드_고유번호1] = 레코드_고유번호1의 StockRec 데이터
                             * 체결량별_인덱스_배열[레코드_고유번호2] = 레코드_고유번호2의 StockRec 데이터
                             * ...
                             * ..
                             * .
                             */
 
                            int 체결량 = 체결량별_인덱스_배열.Key;
 
                            ArrayList 체결시간비교 = new ArrayList();
                            foreach (KeyValuePair<int, StockData.StockRec> row in 체결량별_인덱스_배열.Value.Reverse())
                            {
                                string 체결시간_Mktime = GetMktime(row.Value.HHiiss).ToString();
                                if (체결시간_Mktime == "999999"//시간형식에 맞지않는 쓰레기 데이터가 가끔 온다.
                                {
                                    continue;
                                }
 
                                체결시간비교.Add(체결시간_Mktime);
                            }
 
                            /*
                             * 체결시간비교[0] = 체결시간_MKTIME
                             * 체결시간비교[1] = 체결시간_MKTIME
                             * ...
                             * ..
                             * .
                             */
 
                            //체결량당 체결시간 분석시작
                            if (체결시간비교.Count > 1//시간데이터가 2줄 이상은 있어야 비교가 될테니깐... 어차피 2개라봐야 의미는 없지만...
                            {
                                foreach (KeyValuePair<int, StockData.StockRec> StockRecRow in 체결량별_인덱스_배열.Value.Reverse()) //체결량이 '100'인 StockRec 데이터 루프
                                {
                                    체결시간비교.RemoveAt(0);
 
                                    if (체결시간비교.Count == 0)
                                    {
                                        break;
                                    }
 
                                    int 기준시간_Mktime = GetMktime(StockRecRow.Value.HHiiss);
 
 
                                    //public Dictionary<int, Dictionary<string, string>> 체결량별_타임 = new Dictionary<int, Dictionary<string, string>>();
                                    /*
                                     * 체결량별_타임 딕셔너리는 레코드에 규칙성의 존재유무를 확인하기 위해 존재한다.
                                     * 
                                     * 체결량별_타임[100][체결_MKTIME] = 레코드_고유번호 또는
                                     * 체결량별_타임[100][체결_MKTIME] = "규칙성존재함"
                                     * ...
                                     * ..
                                     * .
                                     */
                                    if (종목데이터.체결량별_타임[체결량][기준시간_Mktime.ToString()] == "규칙성존재함")
                                    {
                                        //기준데이터가 규칙성이 존재하면 패스
                                        continue;
                                    }
 
 
                                    foreach (string 비교시간_Mktime in 체결시간비교)
                                    {
                                        if (종목데이터.체결량별_타임[체결량][비교시간_Mktime] == "규칙성존재함")
                                        {
                                            continue;
                                        }
 
                                        int 시간차_Mktime = int.Parse(비교시간_Mktime) - 기준시간_Mktime;
                                        if (시간차_Mktime != 0//기준데이터와 비교데이터가 같지 않다면
                                        {
                                            //1차 기준데이터 , 2차 비교데이터는 규칙성이 있다고 간주
                                            SET_규칙인터벌(시간차_Mktime, int.Parse(비교시간_Mktime) + 시간차_Mktime, 종목데이터, 체결량);
                                        }
                                    }
                                }
 
                            } //if (체결시간비교.Count > 1)
 
                        } //foreach (KeyValuePair<string, Dictionary<string, StockData.StockRec>> row in 체결량별_인덱스)
                    }
 
                    //분석데이터를 뿌리자
                    //MessageBox.Show(종목데이터.종목코드);
                    종목데이터.SetStockAna();
                    분석데이터_뿌리기(종목데이터);
 
                    listBoxAna.Items.Add(CodeToStockName[현재클릭종목] + " (" + 현재클릭종목 + ")"); //종목분석 완료된거 리스트에 넣기
 
                    if (모든종목분석 == true)
                    {
                        CodeListAutoNumber++;
                        if (CodeList.ContainsKey(CodeListAutoNumber))
                        {
                            if (CodeListAutoNumber < TestCodeCount) //테스트 삼아 10개만 순위분석 해보자.
                            {
                                //1초뒤에 다음종목을 분석하자.
                                타이머.Interval = 1000//100 => 0.1 second
                                타이머.Tick += new EventHandler(timerHandler_AUTO);
                                타이머.Start(); //The countdown is launched!
                            }
                            else // 순위분석 결과를 뿌리자
                            {
                                //체결량별_순위분석['100'] = 5회 규칙이상인 체결건 기준으로 (체결량 * 체결금액) 의 총합
                                //순위분석['1초당결제금액총합'] = 종목명;
                                Dictionary<stringfloat> 순위분석_임시 = new Dictionary<stringfloat>();
                                foreach (KeyValuePair<string, StockData> 최종로우 in 전체종목데이터)
                                {
                                    //string 1초당결제금액총합 = 최종로우.체결량별_순위분석.Sum(v => v.Value);
                                    int 초당결제금액총합 = 최종로우.Value.체결량별_순위분석.Sum(v => v.Value);
 
                                    //    초단위 규칙성 합계금액
                                    //    ---------------------- * 100 => 제일 높은거
                                    //      시가총액 * 0.00001
                                    //string log = "종목이름 : " + 종목이름 + " / 종목코드 : " + 종목코드 + " / 시가총액 : " + 코드번호_To_시가총액[종목코드];
                                    //MessageBox.Show(log);
                                    int 시가총액 = int.Parse(코드번호_To_시가총액[최종로우.Value.종목코드]) * 1000//100000000 * 0.00001 = 1000
                                    float 평균점수 = (float)초당결제금액총합 / 시가총액 * 100;
                                    평균점수 = (float)Math.Round(평균점수, 4);
                                    //MessageBox.Show(초당결제금액총합 + " / " + 시가총액 + " * 100 = " + 평균점수);
 
                                    순위분석_임시[최종로우.Value.종목코드] = 평균점수; //오름차순 정렬 소팅이 안된 배열
                                }
 
                                //오름차순 정렬
                                var 순위분석 = from entry in 순위분석_임시 orderby entry.Value descending select entry;
 
 
                                //오름차순 정렬
                                /*
                                var ListSort = 순위분석_임시.Keys.ToList();
                                ListSort.Sort();
                                foreach (var key in ListSort)
                                {
                                    순위분석[key] = 순위분석_임시[key];
                                }
                                */
 
                                //LogBox.Text = "============ 최종순위 ============" + Environment.NewLine;
                                int TopNumber = 0;
                                foreach (KeyValuePair<stringfloat> 순위로우 in 순위분석)
                                {
                                    TopNumber++;
                                    string 종목코드 = 순위로우.Key;
                                    StockData 종목데이터_임시 = 전체종목데이터[종목코드];
                                    //LogBox.Text += TopNumber + ". " + 종목데이터_임시.종목이름 + "(" + 순위로우.Value + ")" + Environment.NewLine;
 
                                    listBoxRank.Items.Add(TopNumber + ". " + 종목데이터_임시.종목이름 + "(" + 종목데이터_임시.종목코드 + ") => " + 순위로우.Value + "(시총 : " + 코드번호_To_시가총액[종목데이터_임시.종목코드] + ")"); //랭크
                                }
 
                                LogBox.Text += "======= 분석종료 =======" + Environment.NewLine;
                                분석중인지 = false;
                            }
                        } //if (CodeList.ContainsKey(CodeListAutoNumber))
                        else
                        {
                            string now = DateTime.Now.ToString("yyyy/MM/dd hh:mm:ss");
                            MessageBox.Show("모든분석이 끝났습니다." + now);
                        }
                    }
 
                } //else
 
            } //else if (e.sRQName == "체결정보요청")
 
        }
 
        private void timerHandler_AUTO(object sender, System.EventArgs e)
        {
            타이머.Stop();
            타이머 = new System.Windows.Forms.Timer(); //꼭 재시작 해줘야 한다.
            listBoxStock_SelectedIndexChanged_Func(CodeList[CodeListAutoNumber].ToString());
        }
 
        private void 분석데이터_뿌리기(StockData 종목데이터)
        {
            textBoxLoginInfo.Text = "";
            foreach (KeyValuePair<intDictionary<string, ArrayList>> 체결량배열 in 종목데이터.체결량별_규칙분석)
            {
                string RowText = "";
                foreach (KeyValuePair<string, ArrayList> 규칙성배열 in 체결량배열.Value)
                {
                    if (규칙성배열.Value.Count >= 규칙성기준) //5카운트 이상의 규칙성만 인정한다.
                    {
                        RowText += "규칙성 : " + 규칙성배열.Key + "(" + TimeShow(규칙성배열.Key) + ") => " + 규칙성배열.Value.Count + "개" + Environment.NewLine;
                    }
                }
 
                if (RowText != "")
                {
                    textBoxLoginInfo.Text += Environment.NewLine;
                    textBoxLoginInfo.Text += "============== 체결량 분석 [" + 체결량배열.Key + "] ==============" + Environment.NewLine;
                    textBoxLoginInfo.Text += RowText;
                }
            }
 
            if (종목데이터.체결량별_순위분석.Count > 0)
            {
                textBoxLoginInfo.Text += Environment.NewLine;
                foreach (KeyValuePair<intint> row in 종목데이터.체결량별_순위분석)
                {
                    textBoxLoginInfo.Text += "1초당 체결금액[" + row.Key + "] = " + row.Value + Environment.NewLine;
                }
                textBoxLoginInfo.Text += "★ 1초당 토탈 체결금액 -> " + 종목데이터.체결량별_순위분석.Sum(v => v.Value) + Environment.NewLine;
                textBoxLoginInfo.Text += Environment.NewLine;
            }
            else
            {
                textBoxLoginInfo.Text += Environment.NewLine;
                textBoxLoginInfo.Text += " -> 전체  : " + CodeToStockName.Count + " / 현재 : " + CodeListAutoNumber + Environment.NewLine;
                textBoxLoginInfo.Text += Environment.NewLine;
                textBoxLoginInfo.Text += " -> 종목  : " + CodeToStockName[현재클릭종목] + Environment.NewLine;
                textBoxLoginInfo.Text += Environment.NewLine;
                textBoxLoginInfo.Text += " ####### 규칙성이 존재하는 데이터가 없습니다. #######";
            }
        }
 
        private void SET_규칙인터벌(int 시간차_Mktime, int 비교시간_Mktime, StockData 종목데이터, int 체결량)
        {
            int ok_time = chk_range_func(비교시간_Mktime, 종목데이터, 체결량);
            if (ok_time != 0//-1, +1 시간범위안에 규칙성이 존재한다면
            {
                비교시간_Mktime = ok_time;
            }
 
            /*
             * 체결량별_타임 딕셔너리는 레코드에 규칙성의 존재유무를 확인하기 위해 존재한다.
             * 
             * 체결량별_타임[100][체결_MKTIME] = 레코드_고유번호 또는
             * 체결량별_타임[100][체결_MKTIME] = "규칙성존재함"
             * ...
             * ..
             * .
             */
            if (종목데이터.체결량별_타임[체결량].ContainsKey(비교시간_Mktime.ToString())) //세번째 시간 규칙에 맞는 데이터가 존재하고
            {
                if (종목데이터.체결량별_타임[체결량][비교시간_Mktime.ToString()] != "규칙성존재함"//그 세번째 데이터가 아직 다른 규칙성에 종속되어 있지 않다면
                {
                    string 규칙성_초단위 = Regex.Replace(시간차_Mktime.ToString(), @"\d+", n => n.Value.PadLeft(5'0')); //다섯자리 숫자로 만들기
                    string 레코드_고유번호 = 종목데이터.체결량별_타임[체결량][비교시간_Mktime.ToString()];
 
                    //public Dictionary<int, StockRec> 종목레코드 = new Dictionary<int, StockRec>(); //string(레코드 고유번호), StockRec(로우정보)
                    //종목데이터.종목레코드[레코드_고유번호] = StockRec 데이터
                    종목데이터.종목레코드[int.Parse(레코드_고유번호)].규칙인터벌 = 규칙성_초단위;
                    종목데이터.체결량별_타임[체결량][비교시간_Mktime.ToString()] = "규칙성존재함"//규칙성을 종속시킴(다른 규칙성이 대입되는 것을 방지하기 위함.)
 
                    SET_규칙인터벌(시간차_Mktime, 비교시간_Mktime + 시간차_Mktime, 종목데이터, 체결량); //다음 next 타임에도 규칙성이 존재하는지 재귀
                }
            }
        }
 
        private int chk_range_func(int 비교시간_Mktime, StockData 종목데이터, int 체결량)
        {
            int 시작 = 비교시간_Mktime - 범위조정_체결시간;
            int 종료 = 비교시간_Mktime + 범위조정_체결시간;
 
            for (int i = 시작; i <= 종료; i++)
            {
                if(i == 비교시간_Mktime)
                {
                    continue;
                }
 
                if (종목데이터.체결량별_타임[체결량].ContainsKey(i.ToString())) //타임범위(-1, +1)안에 시간 데이터가 존재하는지
                {
                    if (종목데이터.체결량별_타임[체결량][i.ToString()] != "규칙성존재함"//그 시간데이터가 다른 규칙성에 포함되어 있지 않다면
                    {
                        return i;
                    }
                }
            }
 
            return 0;
        }
 
        private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
        {
        }
 
        //분석완료된 종목 row 클릭
        private void listBoxAna_SelectedIndexChanged(object sender, EventArgs e)
        {
            if(분석중인지 == true)
            {
                MessageBox.Show("현재 분석중입니다...");
                return;
            }
 
            string listBoxText = listBoxAna.Items[listBoxAna.SelectedIndex].ToString();
            string[] tmp = listBoxText.Split('(');
            string CodeName = tmp[0].Trim();
            string CodeNumber = tmp[1].Replace(")"string.Empty).Trim();
 
            현재클릭종목 = CodeNumber;
 
            dataGridView1.Rows.Clear();
            StockData 종목데이터 = 전체종목데이터[현재클릭종목];
 
            분석데이터_뿌리기(종목데이터);
 
            foreach (KeyValuePair<int, StockData.StockRec> row in 종목데이터.종목레코드)
            {
                string 규칙인터벌 = "같은거보기";
                if (row.Value.규칙인터벌 != "")
                {
                    규칙인터벌 = row.Value.규칙인터벌;
                }
 
                string[] data = {
                    row.Value.레코드_고유번호.ToString(),
                    row.Value.체결량.ToString(),
                    row.Value.HHiiss,
                    row.Value.체결가.ToString(),
                    규칙인터벌
                };
 
                dataGridView1.Rows.Add(data);
            }
        }
 
        //분석완료된 종목 row 클릭(RANK)
        private void listBoxRank_SelectedIndexChanged(object sender, EventArgs e)
        {
            string listBoxText = listBoxRank.Items[listBoxRank.SelectedIndex].ToString();
            //listBoxRank.Items.Add(TopNumber + ". " + 종목데이터_임시.종목이름 + "(" + 종목데이터_임시.종목코드 + ") => " + 순위로우.Value); //랭크
 
 
            string[] tmp = listBoxText.Split('(');
            string t = tmp[0].Trim();
            string[] tt = t.Split('.');
            string CodeName = tt[1].Trim();
 
            //string CodeNumber = tmp[1].Replace(")", string.Empty).Trim();
            string[] t2 = tmp[1].Split(')');
            string CodeNumber = t2[0].Trim();
            //MessageBox.Show(CodeNumber);
 
            현재클릭종목 = CodeNumber;
 
            dataGridView1.Rows.Clear();
            StockData 종목데이터 = 전체종목데이터[현재클릭종목];
 
            분석데이터_뿌리기(종목데이터);
 
            foreach (KeyValuePair<int, StockData.StockRec> row in 종목데이터.종목레코드)
            {
                string 규칙인터벌 = "같은거보기";
                if(row.Value.규칙인터벌 != "")
                {
                    규칙인터벌 = row.Value.규칙인터벌;
                }
 
                string[] data = {
                    row.Value.레코드_고유번호.ToString(),
                    row.Value.체결량.ToString(),
                    row.Value.HHiiss,
                    row.Value.체결가.ToString(),
                    규칙인터벌
                };
 
                dataGridView1.Rows.Add(data);
            }
        }
 
        private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == 4//같은거보기 클릭
            {
                dataGridView2.Rows.Clear();
 
                DataGridViewRow CR = dataGridView1.CurrentRow;
                string 체결거래량 = CR.Cells[1].Value.ToString();
 
                int RowCnt = dataGridView1.RowCount - 1;
                StockData 종목데이터 = 전체종목데이터[현재클릭종목];
                //ex) 종목레코드['레코드_고유번호'] = StockRec 데이터
                //ex) 종목데이터.체결량별_규칙분석['100']['00060'] = StockRec; => 100개 체결이 60초 간격으로 존재하는 데이터를 넣음.
                for (int i = 0; i < RowCnt; i++)
                {
                    string 체결거래량_row = dataGridView1.Rows[i].Cells[1].Value.ToString();
                    if (체결거래량_row == 체결거래량)
                    {
                        string 체결일 = dataGridView1.Rows[i].Cells[2].Value.ToString();
                        string 레코드_고유번호 = dataGridView1.Rows[i].Cells[0].Value.ToString();
                        string 규칙성 = "-";
                        int 체결일_mktime = GetMktime(체결일);
                        if (종목데이터.체결량별_규칙분석.ContainsKey(int.Parse(체결거래량)))
                        {
                            if (종목데이터.종목레코드[int.Parse(레코드_고유번호)].규칙인터벌 != "")
                            {
                                string 규칙인터벌 = 종목데이터.종목레코드[int.Parse(레코드_고유번호)].규칙인터벌;
                                if (종목데이터.체결량별_규칙분석[int.Parse(체결거래량)][규칙인터벌].Count >= 규칙성기준) //5회 이상인 것들만 보이기
                                {
                                    DateTime NextTime = ConvertFromUnixTimestamp(체결일_mktime + int.Parse(규칙인터벌));
                                    규칙성 = 규칙인터벌 + " / 다음 - " + NextTime.ToString();
                                }
                            }
                        }
 
                        string[] data = {
                            ConvertFromUnixTimestamp(체결일_mktime).ToString(),
                            GetMktime(체결일).ToString(),
                            규칙성
                        };
                        dataGridView2.Rows.Add(data);
                    }
                }
            }
        }
 
        //private void timerHandler(object sender, EventArgs e)
        private void timerHandler(object sender, System.EventArgs e)
        {
            타이머.Stop();
            타이머 = new System.Windows.Forms.Timer(); //꼭 재시작 해줘야 한다.
 
            axKHOpenAPI1.SetInputValue("종목코드", 현재클릭종목);
            axKHOpenAPI1.CommRqData(현재클릭종목 + "_체결정보요청""opt10003"2"0101");
        }
 
        //분석 쓰레드 돌리기
        private void button4_Click(object sender, EventArgs e)
        {
            MessageBox.Show("키움증권에서 1초당 5회로 호출제한을 걸어둔 상태라서 분석 쓰레드는 불가능 ㅠㅠ");
        }
 
        private void textBoxLoginInfo_TextChanged(object sender, EventArgs e)
        {
 
        }
 
        //모든종목분석 클릭
        private void button9_Click(object sender, EventArgs e)
        {
            if(LoginName == null)
            {
                MessageBox.Show("로그인을 해주세요.");
                return;
            }
 
 
            //초기화
            전체종목데이터 = new Dictionary<string, StockData>();
            순위분석 = new Dictionary<stringfloat>(); //최종분석결과
            코드번호_To_시가총액 = new Dictionary<stringstring>();
            CodeListAutoNumber = 0;
            textBoxLoginInfo.Text = "";
            LogBox.Text = "";
            dataGridView1.Rows.Clear();
            listBoxRank.Items.Clear();
            listBoxAna.Items.Clear();
            분석중인지 = true;
 
 
 
            //모든 종목 분석 클릭
            모든종목분석 = true;
 
            //수집시작시간을 저장, GatherStartTime
            string NowTime = DateTime.Now.ToString("HHmmss");
            if (int.Parse(NowTime) > 153000//오후3시30분에 장이 마감되기 때문에 3시30분 이후로는 3시30분으로 현재시간 인식하기
            {
                NowTime = "153000";
            }
            GatherStartTime = GetMktime(NowTime);
 
            listBoxStock_SelectedIndexChanged_Func(CodeList[0].ToString());
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            button1_Click_Func("FIRST");
        }
 
        private void button1_Click_Func(string type)
        {
            long Result;
            Result = axKHOpenAPI1.CommConnect();
            if (Result != 0)
            {
                textBoxLoginInfo.Text = "로그인창 열기 실패!" + Environment.NewLine;
            }
            else
            {
                textBoxLoginInfo.Text = "로그인창 열기 성공!" + Environment.NewLine;
            }
 
            LoginType = type;
        }
 
 
        //Form1.Designer.cs 에서
        //this.axKHOpenAPI1.OnEventConnect += new AxKHOpenAPILib._DKHOpenAPIEvents_OnEventConnectEventHandler(this.axKHOpenAPI1_OnEventConnect);
        //정의함.
        private void axKHOpenAPI1_OnEventConnect(object sender, AxKHOpenAPILib._DKHOpenAPIEvents_OnEventConnectEvent e)
        {
            textBoxLoginInfo.Text = "개인정보 가져오기 성공!" + Environment.NewLine;
            GetInformation();
        }
 
        private void GetInformation()
        {
            textBoxLoginInfo.Text = "";
            textBoxLoginInfo.Text = "LOGIN ID : " + axKHOpenAPI1.GetLoginInfo("USER_ID"+ Environment.NewLine;
            string str = axKHOpenAPI1.GetLoginInfo("ACCNO"+ Environment.NewLine;
            string[] strArray = str.Split(';');
            textBoxLoginInfo.Text = "보유한 계좌 : " + axKHOpenAPI1.GetLoginInfo("ACCOUNT_CNT"+ Environment.NewLine;
 
            foreach (string forstring in strArray)
            {
                if (forstring.Trim() != "")
                {
                    textBoxLoginInfo.Text = "Account : " + forstring + Environment.NewLine;
                }
            }
 
            textBoxLoginInfo.Text = "사용자명 : " + axKHOpenAPI1.GetLoginInfo("USER_NAME"+ Environment.NewLine;
            textBoxLoginInfo.Text += "키보드보안 해지여부(0:정상, 1:해지) : " + axKHOpenAPI1.GetLoginInfo("KEY_BSECGB"+ Environment.NewLine;
            textBoxLoginInfo.Text += "방화벽 설정 여부(0:미설정, 1:설정, 2:해지) : " + axKHOpenAPI1.GetLoginInfo("FIREW_SECGB"+ Environment.NewLine;
 
            LoginName = axKHOpenAPI1.GetLoginInfo("USER_NAME");
 
            //로그인박스 감추기
            //button1.Visible = false;
            button3.Text = LoginName + " 님 어서오셩 (o^3^)o";
            button3.Visible = true;
 
            if(LoginType == "FIRST")
            {
                button2_Click_Func(); //종목리스트 가져오기
            }
            else if(LoginType == "SESSION")
            {
                listBoxStock_SelectedIndexChanged_Func(CodeList[CodeListAutoNumber].ToString());
            }
        }
 
        private void button2_Click(object sender, EventArgs e)
        {
            button2_Click_Func();
        }
 
        private void button2_Click_Func()
        {
            if (LoginName == null)
            {
                textBoxLoginInfo.Text = "로그인을 해주세요!" + Environment.NewLine;
            }
            else
            {
                if(CodeList.Count > 0)
                {
                    //두번째 로그인 이후로는 리스트를 또 받아올 필요없음...
                    //세션테스트를 위해 만들어 놓은거임.
                    return;
                }
 
                //GetCodeListByMarket 메소드는 메소드의 인자로 시장 구분 코드를 문자열로 넘겨주면 메소드의 리턴 값으로 해당 시장에 속해 있는 종목들의 종목 코드 목록을 리턴
                //종목 코드로부터 종목한글명을 얻어오는 메소드는 GetMasterCodeName을 사용 
                //sMarket – 0:장내, 3:ELW, 4:뮤추얼펀드, 5:신주인수권, 6:리츠, 8:ETF, 9:하이일드펀드, 10:코스닥, 30:제3시장
                textBoxLoginInfo.Text = "===== 장내, 코스피 리스트 불러오기 시작 =====" + Environment.NewLine;
                string[] marketList = { "0""10" };
                int InCnt = 0;
                int OutCnt = 0;
                int i = 0;
                foreach (string MNumber in marketList)
                {
                    string result = axKHOpenAPI1.GetCodeListByMarket(MNumber);
                    string[] stockList = result.Split(';');
 
                    if(MNumber == "0")
                    {
                        InCnt = stockList.Count();
                    }
                    else
                    {
                        OutCnt = stockList.Count();
                    }
 
                    foreach (string code in stockList)
                    {
                        if (code != "")
                        {
                            string StockName = axKHOpenAPI1.GetMasterCodeName(code);
                            listBoxStock.Items.Add(StockName + " (" + code + ")");
                            CodeToStockName[code] = StockName;
                            CodeList.Add(i, code);
                            i++;
 
                            //axKHOpenAPI1.SetInputValue("종목코드", code);
                            //axKHOpenAPI1.CommRqData(code + "_주식기본정보", "opt10001", 0, "0101");
                        }
                    }
                }
 
                textBoxLoginInfo.Text = "===== 장내(" + InCnt + "), 코스닥(" + OutCnt + ") 리스트 불러오기 끝 =====" + Environment.NewLine;
 
                /*
                LogBox.Text += "시가총액 정보 시작 =================" + Environment.NewLine;
                foreach (KeyValuePair<string, string> row in 코드번호_To_시가총액)
                {
                    LogBox.Text += row.Key + " => " + row.Value + Environment.NewLine;
                }
                */
            }
        }
 
        private void dataGridView3_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
 
        }
    } //public partial class Form1 : Form
 
//namespace Stock​ 
cs

 


이 게시글은
https://webschool.kr/?v=board_view&board_key=5&idx=20
에서 작성한 글입니다. 소스코드의 경우 해당 블로그에서 이뿌게 노출이 되지 않을 수 있사오니, 위 링크로 들어오셔서 보시길 바랍니다.

반응형