Skip to content

Commit e0acfca

Browse files
committed
py rtd validator
1 parent 8c3c987 commit e0acfca

File tree

4 files changed

+141
-2
lines changed

4 files changed

+141
-2
lines changed

Docs/Project Timeline.md

+2
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,6 @@ https://github.com/ideepcoder/Rtd_Ws_AB_plugin/blob/main/Relay/Server/Python/rel
2323
https://github.com/ideepcoder/Rtd_Ws_AB_plugin/blob/main/Samples/Client/Python/client.py
2424
##### 20250119 - Added Python General Class Wrapper for Vendor/Broker Library
2525
https://github.com/ideepcoder/Rtd_Ws_AB_plugin/blob/main/Samples/Client/Python/vendor_class_wrapper.py
26+
##### 20250128 - Added Python utility script to Validate RTD Json
27+
https://github.com/ideepcoder/Rtd_Ws_AB_plugin/blob/main/Utility%20Scripts/Client/Python/json_validator.py
2628

Docs/WSRTD Doc.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ Inserting historical data into AmiBroker Database
215215
Work in progress, subject to change.
216216
> ALL REQUESTS made by **plug-in TO** Server have only "cmd" and "arg fields"
217217
> Server should REPLY to all above REQUESTS with same "cmd" and "arg" fields. Additionally inserting the "code" which is integer.
218-
> Code values for OK=200, and OTHER/BAD=400
218+
> Code values for OK=200 to 299, and OTHER/BAD=400 to 499. Specific codes are not defined yet.
219219
220220
> ALL REQUESTS made by **Server To** Plug-in will have valid "cmd" and "arg" fields. Additionally, all SERVER-side requests will have code=300 which is integer.
221221
>( The only exceptions is json-RTD and json-HIST formats.)
@@ -336,7 +336,7 @@ R"({"hist")" // Historical Data
336336
Explained here [Amibroker Forum](https://forum.amibroker.com/t/documentation-on-batch-data-plugin-command/39269)
337337
Amibroker [Batch window manual](https://www.amibroker.com/guide/h_batch.html)
338338
339-
Every time the Plug-in receives data, it stores is internally in its own temporary storage and notifies Amibroker of new data. Unfortunately, by design, if the Symbol is not being used by the user is anyway, the plug-in may never be able to "push" the data to AB local Database that is persistent.
339+
Every time the Plug-in receives data, it stores is internally in its own temporary storage and notifies Amibroker of new data. Unfortunately, by design, if the Symbol is not being used by the user in any way, the plug-in may never be able to "push" the data to AB local Database that is persistent.
340340
Therefore, user needs to use a Batch file that consists of an empty Analysis Exploration to force all symbols to fetch data. More on this later.
341341
342342
These are some ways to communicate with the Plug-in from the Amibroker User-Interface OR when the websocket is shutdown and therefore not reachable externally.
+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
'''
2+
// ##### json_validator.py #####
3+
//
4+
// Python utility Script to validate JSON RTD String
5+
// For Historical data, use DebugView.
6+
//
7+
// Performace penalty for Plugin to validate every permutation is unnecessary,
8+
// as a well written CLIENT=APP already performs checks on RTD.
9+
//
10+
///////////////////////////////////////////////////////////////////////
11+
// Author: NSM51
12+
// https://github.com/ideepcoder/Rtd_Ws_AB_plugin/
13+
// https://forum.amibroker.com/u/nsm51/summary
14+
//
15+
// Any use of this source code must include the above notice,
16+
// in the user documentation and internal comments to the code.
17+
'''
18+
19+
20+
import json
21+
22+
## Insert RTD json string in '' quotes to validate
23+
js = '[{"n":"SYM3","d":20250127,"t":230908,"o":189.45,"h":196.32,"l":181.89,"c":194.59,"v":1212,"bp":186.71,"as":10},\
24+
{"n":"SYM2","d":20250127,"t":230908,"o":189.45,"h":196.32,"l":181.89,"c":194.59,"v":1212,"ap":186.71,"bs":10}]'
25+
26+
###############
27+
# Fields used by RTD json
28+
29+
Field_str = [ 'n' ]
30+
Field_num_reqd = [ 'o', 'h', 'l', 'c' ]
31+
Field_num_optional = [ 'v', 'oi', 'x1', 'x2', 's', 'pc', 'bs', 'bp', 'as', 'ap', 'do', 'dh', 'dl' ]
32+
33+
34+
def check_str_reqd( f, r ):
35+
if f in r:
36+
if not isinstance( r[f], str ):
37+
print( f"{f} not str in \n{r}" ); return False
38+
else:
39+
print( f"{f} not found in \n{r}" ); return False
40+
41+
return True
42+
43+
44+
def check_num_reqd( f, r ):
45+
if f in r:
46+
if not isinstance( r[f], (int, float) ):
47+
print( f"{f} not NUM in \n{r}" ); return False
48+
else:
49+
print( f"{f} not found in \n{r}" ); return False
50+
51+
return True
52+
53+
54+
def check_num_opt( f, r ):
55+
if f in r:
56+
if not isinstance( r[f], (int, float) ):
57+
print( f"{f} not NUM in \n{r}" ); return False
58+
59+
return True
60+
61+
62+
'''
63+
Function to validate type of mandatory & optional fields
64+
'''
65+
def json_rtd_validate( js:str ):
66+
67+
if js.startswith('[{"n"'): print(f"\nString MATCH = ok")
68+
else: print(f"\nString MATCH failed"); return
69+
70+
try:
71+
jo = json.loads( js )
72+
print( f"Json parsing = ok" )
73+
except Exception as e:
74+
print( e ); return
75+
76+
77+
if isinstance( jo, list):
78+
print("Outer Array = ok\n")
79+
else:
80+
print( f"Not Array of Quotes"); return
81+
82+
83+
i = 0;
84+
for r in jo:
85+
86+
if not isinstance( r, dict ): print(f"record should be dict"); return
87+
88+
## test mandatory 'n' and type
89+
if not check_str_reqd( 'n', r ): return
90+
91+
## OHLC, test mandatory and type
92+
for ro in Field_num_reqd:
93+
if not check_num_reqd( ro, r ): return
94+
95+
## Optionals, test type
96+
for ro in Field_num_optional:
97+
if not check_num_opt( ro, r ): return
98+
99+
## Date
100+
if 'd' in r:
101+
if type( r['d'] ) is not int:
102+
print( f"d not int \n{r}" ); return
103+
104+
if 't' in r:
105+
if type( r['t'] ) is not int :
106+
print( f"t not int \n{r}" ); return
107+
else:
108+
print( f"t is required with d in \n{r}"); return
109+
110+
elif 'u' in r:
111+
if type( r['u'] ) is not int :
112+
print( f"u not int \n{r}" ); return
113+
114+
elif 'g' in r:
115+
if type( r['g'] ) is not int :
116+
print( f"g not int \n{r}" ); return
117+
118+
else: print( f"d/u/g not found in \n{r}" ); return
119+
120+
print( f"record {i} = ok" ); i += 1
121+
122+
return 1
123+
124+
125+
#### main()
126+
if __name__ == '__main__':
127+
128+
if json_rtd_validate( js ):
129+
print( f"\nFinal validation = OK\n")
130+
else:
131+
print( f"\nFinal validation = FAILED\n" )
132+
133+
#print( js ) ## print original string
134+

Utility Scripts/Python/notice.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
This plugin should be distributed or redisributed with the Documentation
2+
file provided in HTML that contains all the Licence information,
3+
Trademark, Copyright & Other notices.

0 commit comments

Comments
 (0)