feat: add Quant OS A-share baseline
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
"""Small deterministic JoinQuant API harness for local contract tests."""
|
||||
|
||||
import datetime
|
||||
from types import SimpleNamespace
|
||||
|
||||
|
||||
class FakePosition(object):
|
||||
def __init__(self, total_amount=0, closeable_amount=None):
|
||||
self.total_amount = int(total_amount)
|
||||
self.closeable_amount = int(
|
||||
total_amount if closeable_amount is None else closeable_amount
|
||||
)
|
||||
|
||||
|
||||
class FakeJoinQuantHarness(object):
|
||||
"""Install fake hosted functions into a strategy module."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
histories,
|
||||
total_value=1_000_000.0,
|
||||
positions=None,
|
||||
st_symbols=None,
|
||||
):
|
||||
self.histories = {
|
||||
symbol: [float(value) for value in values]
|
||||
for symbol, values in histories.items()
|
||||
}
|
||||
self.options = {}
|
||||
self.benchmark = None
|
||||
self.order_cost = None
|
||||
self.slippage = None
|
||||
self.schedules = []
|
||||
self.orders = []
|
||||
self.order_styles = []
|
||||
self.last_index_request = None
|
||||
self.last_history_request = None
|
||||
self.last_extras_request = None
|
||||
self.st_symbols = set(st_symbols or [])
|
||||
self.current_data = {
|
||||
symbol: SimpleNamespace(
|
||||
paused=False,
|
||||
is_st=False,
|
||||
high_limit=9999.0,
|
||||
low_limit=0.01,
|
||||
)
|
||||
for symbol in histories
|
||||
}
|
||||
self.context = SimpleNamespace(
|
||||
current_dt=datetime.datetime(2026, 7, 20, 9, 30),
|
||||
previous_date=datetime.date(2026, 7, 17),
|
||||
portfolio=SimpleNamespace(
|
||||
total_value=float(total_value),
|
||||
positions=dict(positions or {}),
|
||||
)
|
||||
)
|
||||
self.g = SimpleNamespace()
|
||||
|
||||
def install(self, module):
|
||||
module.g = self.g
|
||||
module.set_option = self.set_option
|
||||
module.run_daily = self.run_daily
|
||||
module.attribute_history = self.attribute_history
|
||||
module.history = self.history
|
||||
module.get_index_stocks = self.get_index_stocks
|
||||
module.get_extras = self.get_extras
|
||||
module.set_benchmark = self.set_benchmark
|
||||
module.set_order_cost = self.set_order_cost
|
||||
module.set_slippage = self.set_slippage
|
||||
module.OrderCost = self.OrderCost
|
||||
module.PriceRelatedSlippage = self.PriceRelatedSlippage
|
||||
module.LimitOrderStyle = self.LimitOrderStyle
|
||||
module.order_target = self.order_target
|
||||
module.get_current_data = self.get_current_data
|
||||
return self
|
||||
|
||||
def set_option(self, key, value):
|
||||
self.options[key] = value
|
||||
|
||||
def set_benchmark(self, symbol):
|
||||
self.benchmark = symbol
|
||||
|
||||
@staticmethod
|
||||
def OrderCost(**kwargs):
|
||||
return SimpleNamespace(**kwargs)
|
||||
|
||||
@staticmethod
|
||||
def PriceRelatedSlippage(value):
|
||||
return SimpleNamespace(value=float(value))
|
||||
|
||||
@staticmethod
|
||||
def LimitOrderStyle(limit_price):
|
||||
return SimpleNamespace(
|
||||
kind="limit",
|
||||
limit_price=float(limit_price),
|
||||
)
|
||||
|
||||
def set_order_cost(self, cost, type=None):
|
||||
self.order_cost = {"cost": cost, "type": type}
|
||||
|
||||
def set_slippage(self, slippage, type=None):
|
||||
self.slippage = {"slippage": slippage, "type": type}
|
||||
|
||||
def run_daily(self, callback, time="open"):
|
||||
self.schedules.append((callback, time))
|
||||
|
||||
def attribute_history(
|
||||
self,
|
||||
symbol,
|
||||
count,
|
||||
unit="1d",
|
||||
fields=None,
|
||||
skip_paused=False,
|
||||
df=False,
|
||||
fq="pre",
|
||||
):
|
||||
del unit, fields, skip_paused, df, fq
|
||||
return {"close": self.histories[symbol][-int(count) :]}
|
||||
|
||||
def history(
|
||||
self,
|
||||
count,
|
||||
unit="1d",
|
||||
field="close",
|
||||
security_list=None,
|
||||
df=False,
|
||||
skip_paused=False,
|
||||
fq="pre",
|
||||
):
|
||||
del unit, field, df, skip_paused, fq
|
||||
symbols = list(security_list or self.histories)
|
||||
self.last_history_request = {
|
||||
"count": int(count),
|
||||
"security_list": symbols,
|
||||
}
|
||||
return {
|
||||
symbol: self.histories[symbol][-int(count) :]
|
||||
for symbol in symbols
|
||||
}
|
||||
|
||||
def get_index_stocks(self, index_symbol, date=None):
|
||||
self.last_index_request = {
|
||||
"index_symbol": index_symbol,
|
||||
"date": date,
|
||||
}
|
||||
return sorted(self.histories)
|
||||
|
||||
def get_extras(
|
||||
self,
|
||||
info,
|
||||
security_list,
|
||||
end_date=None,
|
||||
count=1,
|
||||
df=False,
|
||||
):
|
||||
self.last_extras_request = {
|
||||
"info": info,
|
||||
"security_list": list(security_list),
|
||||
"end_date": end_date,
|
||||
"count": count,
|
||||
"df": df,
|
||||
}
|
||||
return {
|
||||
symbol: [symbol in self.st_symbols]
|
||||
for symbol in security_list
|
||||
}
|
||||
|
||||
def order_target(self, symbol, quantity, style=None):
|
||||
self.orders.append((symbol, int(quantity)))
|
||||
self.order_styles.append((symbol, style))
|
||||
return SimpleNamespace(security=symbol, target_quantity=int(quantity))
|
||||
|
||||
def get_current_data(self):
|
||||
return self.current_data
|
||||
|
||||
def initialize(self, module):
|
||||
self.install(module)
|
||||
module.initialize(self.context)
|
||||
return self
|
||||
|
||||
def run_scheduled(self, index=0):
|
||||
callback = self.schedules[index][0]
|
||||
return callback(self.context)
|
||||
|
||||
def advance_session(self, days=1):
|
||||
previous = self.context.current_dt.date()
|
||||
self.context.previous_date = previous
|
||||
self.context.current_dt += datetime.timedelta(days=int(days))
|
||||
return self
|
||||
Reference in New Issue
Block a user