wangzaijun 1 year ago
commit
d319d9e3b0
43 changed files with 2985 additions and 0 deletions
  1. 33 0
      .gitignore
  2. 2 0
      .logs/access_loglog
  3. BIN
      .mvn/wrapper/maven-wrapper.jar
  4. 18 0
      .mvn/wrapper/maven-wrapper.properties
  5. BIN
      libs/data-calc-0.1.1-SNAPSHOT.jar
  6. 316 0
      mvnw
  7. 188 0
      mvnw.cmd
  8. 113 0
      pom.xml
  9. 15 0
      src/main/java/com/smppw/analysis/DataAnalysisApplication.java
  10. 81 0
      src/main/java/com/smppw/analysis/application/dto/BaseParams.java
  11. 17 0
      src/main/java/com/smppw/analysis/application/dto/RateRiskIndicatorParams.java
  12. 19 0
      src/main/java/com/smppw/analysis/application/dto/TrendParams.java
  13. 281 0
      src/main/java/com/smppw/analysis/application/service/PerformanceService.java
  14. 74 0
      src/main/java/com/smppw/analysis/domain/dao/MarketIndexNavDao.java
  15. 90 0
      src/main/java/com/smppw/analysis/domain/dao/PrivatelyOfferedFundNavDao.java
  16. 77 0
      src/main/java/com/smppw/analysis/domain/dao/PubliclyOfferedFundNavDao.java
  17. 67 0
      src/main/java/com/smppw/analysis/domain/dao/RiskOfFreeNavDao.java
  18. 69 0
      src/main/java/com/smppw/analysis/domain/dao/RongzhiIndexNavDao.java
  19. 54 0
      src/main/java/com/smppw/analysis/domain/pojo/DepositNavDo.java
  20. 112 0
      src/main/java/com/smppw/analysis/domain/pojo/IndexesRzIndexDo.java
  21. 119 0
      src/main/java/com/smppw/analysis/domain/pojo/MarketIndexesDo.java
  22. 74 0
      src/main/java/com/smppw/analysis/domain/pojo/NavDo.java
  23. 77 0
      src/main/java/com/smppw/analysis/domain/pojo/PublicNavDo.java
  24. 20 0
      src/main/java/com/smppw/analysis/domain/service/BaseIndicatorServiceV2.java
  25. 27 0
      src/main/java/com/smppw/analysis/domain/service/NavService.java
  26. 10 0
      src/main/java/com/smppw/analysis/domain/service/SecTypeService.java
  27. 72 0
      src/main/java/com/smppw/analysis/domain/service/impl/BaseIndicatorServiceV2Impl.java
  28. 324 0
      src/main/java/com/smppw/analysis/domain/service/impl/NavServiceImpl.java
  29. 105 0
      src/main/java/com/smppw/analysis/domain/service/impl/SecTypeServiceImpl.java
  30. 15 0
      src/main/java/com/smppw/analysis/infrastructure/persistence/DepositNavDoMapper.java
  31. 16 0
      src/main/java/com/smppw/analysis/infrastructure/persistence/IndexesRzIndexDoMapper.java
  32. 32 0
      src/main/java/com/smppw/analysis/infrastructure/persistence/MarketIndexesDoMapper.java
  33. 24 0
      src/main/java/com/smppw/analysis/infrastructure/persistence/NavDoMapper.java
  34. 13 0
      src/main/java/com/smppw/analysis/infrastructure/persistence/PublicNavDoMapper.java
  35. 48 0
      src/main/java/com/smppw/analysis/infrastructure/utils/DateValueUtil.java
  36. 26 0
      src/main/java/com/smppw/analysis/interfaces/FundApi.java
  37. 54 0
      src/main/resources/application.yaml
  38. 42 0
      src/main/resources/mapping/DepositNavDoMapper.xml
  39. 57 0
      src/main/resources/mapping/IndexesRzIndexDoMapper.xml
  40. 95 0
      src/main/resources/mapping/MarketIndexesDoMapper.xml
  41. 52 0
      src/main/resources/mapping/NavDoMapper.xml
  42. 44 0
      src/main/resources/mapping/PublicNavDoMapper.xml
  43. 13 0
      src/test/java/com/smppw/analysis/DataAnalysisApplicationTests.java

+ 33 - 0
.gitignore

@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/

+ 2 - 0
.logs/access_loglog

@@ -0,0 +1,2 @@
+127.0.0.1 - - [02/Aug/2023:11:19:37 +0800] "GET /v1/api/fund/indicators?startDate=2020-12-28&endDate=2023-02-28&frequency=Default&benchmarkId=IN00000008&refIds=IN00000008&fundId=HF00003KW9&timeRange=Custom&riskOfFreeId=IN0000000M&raiseType=Private&strategy=Equity&navType=CumulativeNav&calcExtraRet=0&secIds=&userId=1196862 HTTP/1.1" 500 7777
+127.0.0.1 - - [02/Aug/2023:11:21:14 +0800] "GET /v1/api/fund/indicators?startDate=2020-12-28&endDate=2023-02-28&frequency=Default&benchmarkId=IN00000008&refIds=IN00000008&fundId=HF00003KW9&timeRange=Custom&riskOfFreeId=IN0000000M&raiseType=Private&strategy=Equity&navType=CumulativeNav&calcExtraRet=0&secIds=&userId=1196862 HTTP/1.1" 500 7777

BIN
.mvn/wrapper/maven-wrapper.jar


+ 18 - 0
.mvn/wrapper/maven-wrapper.properties

@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar

BIN
libs/data-calc-0.1.1-SNAPSHOT.jar


+ 316 - 0
mvnw

@@ -0,0 +1,316 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#    https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+#   JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+#   M2_HOME - location of maven2's installed home dir
+#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
+#     e.g. to debug Maven itself, use
+#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+  if [ -f /usr/local/etc/mavenrc ] ; then
+    . /usr/local/etc/mavenrc
+  fi
+
+  if [ -f /etc/mavenrc ] ; then
+    . /etc/mavenrc
+  fi
+
+  if [ -f "$HOME/.mavenrc" ] ; then
+    . "$HOME/.mavenrc"
+  fi
+
+fi
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+  CYGWIN*) cygwin=true ;;
+  MINGW*) mingw=true;;
+  Darwin*) darwin=true
+    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+    if [ -z "$JAVA_HOME" ]; then
+      if [ -x "/usr/libexec/java_home" ]; then
+        export JAVA_HOME="`/usr/libexec/java_home`"
+      else
+        export JAVA_HOME="/Library/Java/Home"
+      fi
+    fi
+    ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+  if [ -r /etc/gentoo-release ] ; then
+    JAVA_HOME=`java-config --jre-home`
+  fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+  ## resolve links - $0 may be a link to maven's home
+  PRG="$0"
+
+  # need this for relative symlinks
+  while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+      PRG="$link"
+    else
+      PRG="`dirname "$PRG"`/$link"
+    fi
+  done
+
+  saveddir=`pwd`
+
+  M2_HOME=`dirname "$PRG"`/..
+
+  # make it fully qualified
+  M2_HOME=`cd "$M2_HOME" && pwd`
+
+  cd "$saveddir"
+  # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME=`cygpath --unix "$M2_HOME"`
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME="`(cd "$M2_HOME"; pwd)`"
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+  javaExecutable="`which javac`"
+  if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+    # readlink(1) is not available as standard on Solaris 10.
+    readLink=`which readlink`
+    if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+      if $darwin ; then
+        javaHome="`dirname \"$javaExecutable\"`"
+        javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+      else
+        javaExecutable="`readlink -f \"$javaExecutable\"`"
+      fi
+      javaHome="`dirname \"$javaExecutable\"`"
+      javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+      JAVA_HOME="$javaHome"
+      export JAVA_HOME
+    fi
+  fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+  if [ -n "$JAVA_HOME"  ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+      # IBM's JDK on AIX uses strange locations for the executables
+      JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+      JAVACMD="$JAVA_HOME/bin/java"
+    fi
+  else
+    JAVACMD="`\\unset -f command; \\command -v java`"
+  fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+  echo "Error: JAVA_HOME is not defined correctly." >&2
+  echo "  We cannot execute $JAVACMD" >&2
+  exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+  echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+  if [ -z "$1" ]
+  then
+    echo "Path not specified to find_maven_basedir"
+    return 1
+  fi
+
+  basedir="$1"
+  wdir="$1"
+  while [ "$wdir" != '/' ] ; do
+    if [ -d "$wdir"/.mvn ] ; then
+      basedir=$wdir
+      break
+    fi
+    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+    if [ -d "${wdir}" ]; then
+      wdir=`cd "$wdir/.."; pwd`
+    fi
+    # end of workaround
+  done
+  echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+  if [ -f "$1" ]; then
+    echo "$(tr -s '\n' ' ' < "$1")"
+  fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+  exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Found .mvn/wrapper/maven-wrapper.jar"
+    fi
+else
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+    fi
+    if [ -n "$MVNW_REPOURL" ]; then
+      jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+    else
+      jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+    fi
+    while IFS="=" read key value; do
+      case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+      esac
+    done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Downloading from: $jarUrl"
+    fi
+    wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+    if $cygwin; then
+      wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+    fi
+
+    if command -v wget > /dev/null; then
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Found wget ... using wget"
+        fi
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+        else
+            wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+        fi
+    elif command -v curl > /dev/null; then
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Found curl ... using curl"
+        fi
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            curl -o "$wrapperJarPath" "$jarUrl" -f
+        else
+            curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+        fi
+
+    else
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Falling back to using Java to download"
+        fi
+        javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+        # For Cygwin, switch paths to Windows format before running javac
+        if $cygwin; then
+          javaClass=`cygpath --path --windows "$javaClass"`
+        fi
+        if [ -e "$javaClass" ]; then
+            if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+                if [ "$MVNW_VERBOSE" = true ]; then
+                  echo " - Compiling MavenWrapperDownloader.java ..."
+                fi
+                # Compiling the Java class
+                ("$JAVA_HOME/bin/javac" "$javaClass")
+            fi
+            if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+                # Running the downloader
+                if [ "$MVNW_VERBOSE" = true ]; then
+                  echo " - Running MavenWrapperDownloader.java ..."
+                fi
+                ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+            fi
+        fi
+    fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+  echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME=`cygpath --path --windows "$M2_HOME"`
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+    MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+  $MAVEN_OPTS \
+  $MAVEN_DEBUG_OPTS \
+  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+  "-Dmaven.home=${M2_HOME}" \
+  "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

+ 188 - 0
mvnw.cmd

@@ -0,0 +1,188 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements.  See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership.  The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License.  You may obtain a copy of the License at
+@REM
+@REM    https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied.  See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM     e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+    IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Found %WRAPPER_JAR%
+    )
+) else (
+    if not "%MVNW_REPOURL%" == "" (
+        SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+    )
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Couldn't find %WRAPPER_JAR%, downloading it ...
+        echo Downloading from: %DOWNLOAD_URL%
+    )
+
+    powershell -Command "&{"^
+		"$webclient = new-object System.Net.WebClient;"^
+		"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+		"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+		"}"^
+		"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+		"}"
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Finished downloading %WRAPPER_JAR%
+    )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+  %JVM_CONFIG_MAVEN_PROPS% ^
+  %MAVEN_OPTS% ^
+  %MAVEN_DEBUG_OPTS% ^
+  -classpath %WRAPPER_JAR% ^
+  "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+  %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%

+ 113 - 0
pom.xml

@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>3.0.9</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+    <groupId>com.smppw</groupId>
+    <artifactId>data-analysis</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>data-analysis</name>
+    <description>Demo project for Spring Boot</description>
+    <properties>
+        <java.version>17</java.version>
+        <hutool-version>5.8.12</hutool-version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-tomcat</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-undertow</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter</artifactId>
+            <version>3.0.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.smppw</groupId>
+            <artifactId>data-calc</artifactId>
+            <version>1-0.SNAPSHOT</version>
+            <scope>system</scope>
+            <systemPath>${project.basedir}/libs/data-calc-0.1.1-SNAPSHOT.jar</systemPath>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-core</artifactId>
+            <version>${hutool-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-json</artifactId>
+            <version>${hutool-version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+            <scope>runtime</scope>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>com.mysql</groupId>
+            <artifactId>mysql-connector-j</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter-test</artifactId>
+            <version>3.0.2</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.graalvm.buildtools</groupId>
+                <artifactId>native-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>
+                            <groupId>org.projectlombok</groupId>
+                            <artifactId>lombok</artifactId>
+                        </exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 15 - 0
src/main/java/com/smppw/analysis/DataAnalysisApplication.java

@@ -0,0 +1,15 @@
+package com.smppw.analysis;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@MapperScan("com.smppw.analysis.infrastructure.persistence")
+@SpringBootApplication
+public class DataAnalysisApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(DataAnalysisApplication.class, args);
+    }
+
+}

+ 81 - 0
src/main/java/com/smppw/analysis/application/dto/BaseParams.java

@@ -0,0 +1,81 @@
+package com.smppw.analysis.application.dto;
+
+import com.smppw.common.pojo.enums.Frequency;
+import com.smppw.common.pojo.enums.NavType;
+import com.smppw.common.pojo.enums.RaiseType;
+import com.smppw.common.pojo.enums.TimeRange;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author wangzaijun
+ * @date 2023/3/3 17:25
+ * @description 基金详情页接口公共请求参数
+ */
+@Setter
+@Getter
+public abstract class BaseParams implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 标的id,包括基金、机构和经理
+     */
+    private List<String> fundId;
+    /**
+     * 基准
+     */
+    private String benchmarkId;
+    /**
+     * 对比指数
+     */
+    private List<String> secIds;
+    /**
+     * 净值类型
+     */
+    private NavType navType;
+    /**
+     * 时段
+     */
+    private TimeRange timeRange;
+    /**
+     * 频率
+     */
+    private Frequency frequency;
+    /**
+     * 标的类型
+     */
+    private RaiseType raiseType;
+    /**
+     * 二级策略
+     */
+    private String strategy;
+    /**
+     * 开始日期
+     */
+    private String startDate;
+    /**
+     * 结束日期
+     */
+    private String endDate;
+    /**
+     * 当前登录用户id
+     */
+    private Integer userId;
+
+    /**
+     * 是否计算费后:false-不计算,true-计算
+     */
+    private Boolean isExtract;
+
+    /**
+     * 是否多标的,根据传参判断
+     *
+     * @return /
+     */
+    public boolean multiSec() {
+        return this.fundId.size() > 1;
+    }
+}

+ 17 - 0
src/main/java/com/smppw/analysis/application/dto/RateRiskIndicatorParams.java

@@ -0,0 +1,17 @@
+package com.smppw.analysis.application.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author wangzaijun
+ * @date 2023/3/3 17:26
+ * @description 收益风险指标接口特定请求参数
+ */
+@Setter
+@Getter
+public class RateRiskIndicatorParams extends BaseParams {
+    private String riskOfFreeId;
+    private Double riskOfFreeValue;
+    private Boolean calcExtraRet;
+}

+ 19 - 0
src/main/java/com/smppw/analysis/application/dto/TrendParams.java

@@ -0,0 +1,19 @@
+package com.smppw.analysis.application.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author wangzaijun
+ * @date 2023/3/6 8:38
+ * @description 业绩走势接口请求参数
+ */
+@Setter
+@Getter
+public class TrendParams extends BaseParams {
+
+    /**
+     * 1: 展示 2:不展示
+     */
+    private String showTrade;
+}

+ 281 - 0
src/main/java/com/smppw/analysis/application/service/PerformanceService.java

@@ -0,0 +1,281 @@
+package com.smppw.analysis.application.service;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.collection.ListUtil;
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.NumberUtil;
+import cn.hutool.core.util.StrUtil;
+import com.smppw.analysis.application.dto.BaseParams;
+import com.smppw.analysis.application.dto.RateRiskIndicatorParams;
+import com.smppw.analysis.domain.service.BaseIndicatorServiceV2;
+import com.smppw.common.exception.APIException;
+import com.smppw.common.exception.DataException;
+import com.smppw.common.pojo.CommonData;
+import com.smppw.common.pojo.IStrategy;
+import com.smppw.common.pojo.dto.calc.IndicatorCalcIndexDataDto;
+import com.smppw.common.pojo.dto.calc.IndicatorCalcPropertyDto;
+import com.smppw.common.pojo.dto.calc.IndicatorCalcSecDataDto;
+import com.smppw.common.pojo.dto.indicator.CalcMultipleSecMultipleTimeRangeIndicatorReq;
+import com.smppw.common.pojo.dto.indicator.DateIntervalDto;
+import com.smppw.common.pojo.enums.*;
+import com.smppw.constants.Consts;
+import com.smppw.core.reta.calc.PerformanceConsistency;
+import com.smppw.utils.CommonUtil;
+import com.smppw.utils.StrategyHandleUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+@Service
+public class PerformanceService {
+    private final Logger logger = LoggerFactory.getLogger(PerformanceService.class);
+    private final BaseIndicatorServiceV2 baseIndicatorServiceV2;
+
+    public PerformanceService(BaseIndicatorServiceV2 baseIndicatorServiceV2) {
+        this.baseIndicatorServiceV2 = baseIndicatorServiceV2;
+    }
+
+    public Map<String, Object> rateRiskIndicators(RateRiskIndicatorParams params, List<Indicator> indicators, List<Indicator> geoIndicators) {
+        try {
+            // 1.参数处理
+            this.checkParams(params);
+            List<String> refIds = params.getFundId();
+            List<String> secIds = this.getSecIdsByParams(params);
+            // 差集求指数id集合,包括基�
+            List<String> indexIds = CollectionUtil.subtractToList(secIds, refIds);
+            String riskOfFreeId = params.getRiskOfFreeId();
+            Double riskOfFreeValue = params.getRiskOfFreeValue();
+            if (StrUtil.isBlank(riskOfFreeId)) {
+                riskOfFreeId = Consts.RISK_OF_FREE;
+            } else if (NumberUtil.isNumber(riskOfFreeId)) {
+                riskOfFreeValue = Double.parseDouble(riskOfFreeId);
+                riskOfFreeId = null;
+            }
+            CalcMultipleSecMultipleTimeRangeIndicatorReq req = this.buildCalcReq(params, indicators, geoIndicators, DateIntervalType.CustomInterval, null);
+            req.setRiskOfFreeId(riskOfFreeId);
+            req.setRiskOfFreeValue(riskOfFreeValue);
+            req.setIfExtract(params.getIsExtract() != null && params.getIsExtract());
+
+            // 2.指标计算
+            Map<String, List<IndicatorCalcPropertyDto>> indicator = this.baseIndicatorServiceV2.calcMultipleSecMultipleTimeRangeIndicator(req);
+
+            // 3.返回结果处理
+            Map<String, Object> valuesMap = MapUtil.newHashMap(true);
+            Map<String, Object> indexValuesMap = MapUtil.newHashMap(true);
+            for (String refId : refIds) {
+                IndicatorCalcPropertyDto dto = Optional.ofNullable(indicator.get(refId)).filter(e -> !e.isEmpty()).map(e -> e.get(0)).orElse(null);
+                // 标的指标
+                Map<String, String> indicatorValues = Optional.ofNullable(dto).map(IndicatorCalcPropertyDto::getSecData).map(IndicatorCalcSecDataDto::getIndicatorValueMap).orElse(MapUtil.empty());
+                // 标的几何指标
+                Map<String, String> geoIndicatorValues = Optional.ofNullable(dto).map(IndicatorCalcPropertyDto::getSecData).map(IndicatorCalcSecDataDto::getExtraGeoIndicatorValueMap).orElse(MapUtil.empty());
+                // 指数指标,包括基�
+                Map<String, Map<String, String>> indexIndicatorValuesMap = Optional.ofNullable(dto).map(IndicatorCalcPropertyDto::getIndexData).map(IndicatorCalcIndexDataDto::getIndexIndicatorValueMap).orElse(MapUtil.empty());
+                // 指数几何指标
+                Map<String, Map<String, String>> indexGeoIndicatorValuesMap = Optional.ofNullable(dto).map(IndicatorCalcPropertyDto::getIndexData).map(IndicatorCalcIndexDataDto::getIndexGeoExtraIndicatorValueMap).orElse(MapUtil.empty());
+                // 标的和指数分别处理最大回撤指标,并合并指标结果到一个map�
+                Map<String, String> values = this.handleMaxDrawdown(indicatorValues, refId, null, false);
+                Map<String, String> geoValues = this.handleMaxDrawdown(geoIndicatorValues, refId, null, true);
+                Map<String, String> unionValues = MapUtil.<String, String>builder().putAll(values).putAll(geoValues).build();
+                valuesMap.put(refId, unionValues);
+                for (String indexId : indexIds) {
+                    if (indexValuesMap.containsKey(indexId)) {
+                        continue;
+                    }
+                    Map<String, String> indexValues = this.handleMaxDrawdown(indexIndicatorValuesMap.get(indexId), indexId, null, false);
+                    Map<String, String> indexGeoValues = this.handleMaxDrawdown(indexGeoIndicatorValuesMap.get(indexId), indexId, params.getBenchmarkId(), true);
+                    Map<String, String> unionIndexValues = MapUtil.<String, String>builder().putAll(indexValues).putAll(indexGeoValues).build();
+                    indexValuesMap.put(indexId, unionIndexValues);
+                }
+            }
+
+            // 返回结果对象构建
+            Map<String, Object> dataset = MapUtil.builder(valuesMap).putAll(indexValuesMap).build();
+            Map<String, Object> extInfos = MapUtil.<String, Object>builder("endDate", params.getStartDate() + "~" + params.getEndDate()).build();
+//            Map<String, String> productNameMapping = this.secId2NameService.query(secIds);
+            Map<String, String> productNameMapping = MapUtil.newHashMap(); // todo
+            CommonData<Map<String, Object>> data = CommonData.<Map<String, Object>>builder().dataset(dataset).productNameMapping(productNameMapping).extInfos(extInfos).build();
+            return CommonUtil.covertToMap(data, "endDate");
+        } catch (Exception e) {
+            logger.error(String.format("基金收益风险指标计算错误:%s", e.getMessage()));
+        }
+        return MapUtil.newHashMap();
+    }
+
+    /**
+     * 构建指标计算参数
+     *
+     * @param params          接口请求参数
+     * @param indicators      要计算的普通指标
+     * @param geoIndicators   geo指标
+     * @param dateIntervalMap 时段
+     * @param <P>             类型参数
+     * @return /
+     */
+    private <P extends BaseParams> CalcMultipleSecMultipleTimeRangeIndicatorReq buildCalcReq(P params, List<Indicator> indicators, List<Indicator> geoIndicators, Map<String, List<DateIntervalDto>> dateIntervalMap) {
+        List<String> refIds = params.getFundId();
+        List<String> secIds = this.getSecIdsByParams(params);
+        // 差集求指数id集合,包括基准
+        List<String> indexIds = CollectionUtil.subtractToList(secIds, refIds);
+        Map<String, String> benchmarkIdMap = MapUtil.newHashMap(true);
+        for (String refId : refIds) {
+            if (StrUtil.isBlank(params.getBenchmarkId())) {
+                continue;
+            }
+            benchmarkIdMap.put(refId, params.getBenchmarkId());
+        }
+        return CalcMultipleSecMultipleTimeRangeIndicatorReq.builder()
+                .mainSecIdList(refIds)
+                .secBenchmarkIdMap(benchmarkIdMap)
+                .indexIdList(indexIds)
+                .raiseType(params.getRaiseType())
+                .strategy(this.getOriginStrategy(params))
+                .visibility(Visibility.Both)
+                .dataFrequency(params.getFrequency())
+                .navType(params.getNavType())
+                .userId(params.getUserId())
+                .secDateIntervalDtoListMap(dateIntervalMap)
+                .indicatorList(indicators)
+                .geoExtraindicatorList(geoIndicators)
+                .ifAnnualize(true)
+                .calcIndexRetIndicatorValue(true)
+                .ifExtract(params.getIsExtract() != null && params.getIsExtract())
+                .ifConvertPerformanceConsistencyWord(true).build();
+    }
+
+    /**
+     * 构建指标计算请求参数
+     *
+     * @param params           /
+     * @param indicatorList    要计算的普通指标列表
+     * @param geoIndicatorList 几何指标列表
+     * @param dateIntervalType /
+     * @param frequency        /
+     * @param <P>              /
+     * @return /
+     */
+    protected <P extends BaseParams> CalcMultipleSecMultipleTimeRangeIndicatorReq buildCalcReq(P params, List<Indicator> indicatorList, List<Indicator> geoIndicatorList,
+                                                                                               DateIntervalType dateIntervalType, Frequency frequency) {
+        List<String> refIds = params.getFundId();
+        DateIntervalDto dateInterval = this.buildDateIntervalByParams(params, dateIntervalType, frequency);
+        Map<String, List<DateIntervalDto>> dateIntervalMap = MapUtil.newHashMap(true);
+        for (String refId : refIds) {
+            dateIntervalMap.put(refId, ListUtil.toList(dateInterval));
+        }
+        return this.buildCalcReq(params, indicatorList, geoIndicatorList, dateIntervalMap);
+    }
+
+    /**
+     * 根据请求参数构建 DateIntervalDto 对象
+     *
+     * @param params           请求参数,需继承 CommonParams
+     * @param dateIntervalType 时段类型
+     * @param frequency        接口传递的频率,一般为滚动计算时传递的滚动频率
+     * @param <P>              参数类型
+     * @return /
+     */
+    protected <P extends BaseParams> DateIntervalDto buildDateIntervalByParams(P params, DateIntervalType dateIntervalType, Frequency frequency) {
+        if (dateIntervalType == null) {
+            dateIntervalType = DateIntervalType.DefaultInterval;
+        }
+        if (frequency == null) {
+            frequency = params.getFrequency();
+        }
+        return DateIntervalDto.builder()
+                .id(dateIntervalType.name())
+                .startDate(params.getStartDate())
+                .endDate(params.getEndDate())
+                .timeRange(params.getTimeRange())
+                .dateIntervalType(dateIntervalType)
+                .frequency(frequency).build();
+    }
+
+
+    /**
+     * 策略枚举,从字符串转换。实现类太多不能自动转换需特殊处理
+     */
+    protected <P extends BaseParams> IStrategy getOriginStrategy(P params) {
+        return StrategyHandleUtils.getStrategy(params.getStrategy());
+    }
+
+    /**
+     * 公共参数检验,部分参数为空时设置默认值.
+     *
+     * @param params 请求参数
+     * @param <P>    类型参数
+     */
+    protected <P extends BaseParams> void checkParams(P params) {
+        if (params.getFundId() == null || params.getFundId().isEmpty()) {
+            throw new APIException("fundId 参数不能为空");
+        }
+        if (StrUtil.isBlank(params.getStartDate()) && StrUtil.isBlank(params.getEndDate())) {
+            throw new DataException(null);
+        }
+        if (params.getNavType() == null) {
+            logger.warn(String.format("navType 为null, 设置一个初始值:%s", NavType.CumulativeNav));
+            params.setNavType(NavType.CumulativeNav);
+        }
+        if (params.getFrequency() == null) {
+            logger.warn(String.format("frequency 为null, 设置一个初始值:%s", Frequency.Daily));
+            params.setFrequency(Frequency.Daily);
+        }
+    }
+
+    /**
+     * 从请求参数中获取所有标的并集集合
+     *
+     * @param params 公共请求参数
+     * @param <P>    类型
+     * @return /
+     */
+    protected <P extends BaseParams> List<String> getSecIdsByParams(P params) {
+        List<String> tempList = ListUtil.list(true);
+        tempList.addAll(params.getFundId());
+        if (StrUtil.isNotBlank(params.getBenchmarkId())) {
+            tempList.add(params.getBenchmarkId());
+        }
+        return params.getSecIds() == null ? tempList : CollUtil.addAllIfNotContains(tempList, params.getSecIds());
+    }
+
+    /**
+     * 处理最大回撤问题,是否已恢复
+     *
+     * @param indicatorValues 指标结果
+     * @param secId           标的id
+     * @param benchmarkId     基准
+     * @param geo             是否处理geo几何指标
+     * @return 新map
+     */
+    protected Map<String, String> handleMaxDrawdown(Map<String, String> indicatorValues, String secId, String benchmarkId, boolean geo) {
+        Map<String, String> result = MapUtil.newHashMap();
+        String maxDrawdown = indicatorValues.get(Indicator.MaxDrawdown.name());
+        String consistency = indicatorValues.get(Indicator.PerformanceConsistency.name());
+        if (StrUtil.isNotBlank(maxDrawdown) && new BigDecimal(maxDrawdown).compareTo(BigDecimal.ZERO) > 0) {
+            if (StrUtil.isBlank(indicatorValues.get(Indicator.MaxDrawdownRecureDate.name()))) {
+                indicatorValues.put(Indicator.MaxDrawdownRecureDate.name(), "最大回撤未修复");
+            }
+            if (StrUtil.isBlank(indicatorValues.get(Indicator.MaxDrawdownRecureIntervalDays.name()))) {
+                indicatorValues.put(Indicator.MaxDrawdownRecureIntervalDays.name(), "最大回撤未修复");
+            }
+            if (StrUtil.isBlank(indicatorValues.get(Indicator.MaxDrawdownRecureInterval.name()))) {
+                indicatorValues.put(Indicator.MaxDrawdownRecureInterval.name(), "最大回撤未修复");
+            }
+        }
+        if (StrUtil.isEmpty(consistency)) {
+            indicatorValues.put(Indicator.PerformanceConsistency.name(), PerformanceConsistency.convert2Word(null));
+        } else {
+            indicatorValues.put(Indicator.PerformanceConsistency.name(), PerformanceConsistency.convert2Word(Double.parseDouble(consistency)));
+        }
+        if (geo) {
+            indicatorValues.forEach((k, v) -> result.put("geoExcess" + k, secId != null && secId.equals(benchmarkId) ? null : v));
+        } else {
+            result.putAll(indicatorValues);
+        }
+        return result;
+    }
+}

+ 74 - 0
src/main/java/com/smppw/analysis/domain/dao/MarketIndexNavDao.java

@@ -0,0 +1,74 @@
+package com.smppw.analysis.domain.dao;
+
+import com.smppw.analysis.domain.pojo.MarketIndexesDo;
+import com.smppw.analysis.infrastructure.persistence.MarketIndexesDoMapper;
+import com.smppw.common.pojo.dto.NavDto;
+import com.smppw.constants.DateConst;
+import com.smppw.utils.DateUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Repository
+public class MarketIndexNavDao {
+
+    @Autowired
+    private MarketIndexesDoMapper marketIndexesDoMapper;
+
+    public Map<String, List<NavDto>> getNav(List<String> indexIdList, String startDate, String endDate, boolean needUpdateAndCreateTime) {
+        List<MarketIndexesDo> navDoList = marketIndexesDoMapper.listNavByTimeInterval(indexIdList, startDate, endDate, needUpdateAndCreateTime);
+        Map<String, List<NavDto>> indexIdNavDtoListMap = navDoListToNavDtoMap(navDoList);
+        return indexIdNavDtoListMap;
+    }
+
+    public List<MarketIndexesDo> getIndexNavByPriceDate(String indexId, List<String> priceDateList) {
+        return marketIndexesDoMapper.selectIndexNavByPriceDate(indexId, priceDateList);
+    }
+
+    /**
+     * 领域对象集合转为数据传输对象集合
+     *
+     * @param navDoList 领域对象集合
+     * @return 数据传输对象集合  key-基金ID  value-数据传输对象集合
+     */
+    private Map<String, List<NavDto>> navDoListToNavDtoMap(List<MarketIndexesDo> navDoList) {
+        Map<String, List<NavDto>> fundIdNavDtoListMap = new HashMap<>();
+
+        if (navDoList == null) {
+            return fundIdNavDtoListMap;
+        }
+
+        for (MarketIndexesDo navDo : navDoList) {
+            NavDto navDto = new NavDto();
+            navDto.setFundId(navDo.getIndexId());
+            if (navDo.getPriceDate() == null || navDo.getClose() == null) {
+                continue;
+            }
+            navDto.setPriceDate(DateUtil.DateToString(navDo.getPriceDate(), DateConst.YYYY_MM_DD));
+            navDto.setOriginalNav(navDo.getClose());
+            navDto.setCumulativeNav(navDo.getClose());
+            navDto.setCumulativeNavWithdrawal(navDo.getClose());
+            if (navDo.getUpdatetime() != null) {
+                navDto.setUpdatetime(DateUtil.DateToString(navDo.getUpdatetime(), DateConst.YYYY_MM_DD_HH_MM_SS));
+            }
+            if (navDo.getCreatetime() != null) {
+                navDto.setCreatetime(DateUtil.DateToString(navDo.getCreatetime(), DateConst.YYYY_MM_DD));
+            }
+
+            if (fundIdNavDtoListMap.containsKey(navDo.getIndexId())) {
+                List<NavDto> navDtoList = fundIdNavDtoListMap.get(navDo.getIndexId());
+                navDtoList.add(navDto);
+            } else {
+                List<NavDto> navDtoList = new ArrayList<>();
+                navDtoList.add(navDto);
+                fundIdNavDtoListMap.put(navDo.getIndexId(), navDtoList);
+            }
+        }
+        return fundIdNavDtoListMap;
+    }
+
+}

+ 90 - 0
src/main/java/com/smppw/analysis/domain/dao/PrivatelyOfferedFundNavDao.java

@@ -0,0 +1,90 @@
+package com.smppw.analysis.domain.dao;
+
+import com.smppw.analysis.domain.pojo.NavDo;
+import com.smppw.analysis.infrastructure.persistence.NavDoMapper;
+import com.smppw.common.pojo.dto.NavDto;
+import com.smppw.common.pojo.enums.NavType;
+import com.smppw.constants.DateConst;
+import com.smppw.constants.NavConst;
+import com.smppw.utils.DateUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+import java.util.*;
+
+@Repository
+public class PrivatelyOfferedFundNavDao {
+
+    @Autowired
+    private NavDoMapper navDoMapper;
+
+    public Map<String, List<NavDto>> getNav(List<String> fundIdList, String startDate, String endDate, NavType navType, boolean needUpdateAndCreateTime) {
+        String navFieldSql = "";
+        List<NavDo> navDoList = null;
+        if (NavType.CumulativeNav == navType) {
+            navFieldSql = NavConst.CUMULATIVE_NAV_SQL_FIELD;
+        } else if (NavType.OriginalNav == navType) {
+            navFieldSql = NavConst.NAV_SQL_FIELD;
+        } else if (NavType.WithdrawalNav == navType) {
+            navFieldSql = NavConst.CUMULATIVE_NAV_WITHDRAWAL_SQL_FIELD;
+        } else if (NavType.All == navType) {
+            navFieldSql = NavConst.CUMULATIVE_NAV_SQL_FIELD + "," + NavConst.NAV_SQL_FIELD + "," + NavConst.CUMULATIVE_NAV_WITHDRAWAL_SQL_FIELD;
+        }
+        navDoList = navDoMapper.listNavByTimeInterval(fundIdList, startDate, endDate, navFieldSql, needUpdateAndCreateTime);
+        Map<String, List<NavDto>> fundIdNavDtoListMap = navDoListToNavDtoMap(navDoList);
+        return fundIdNavDtoListMap;
+    }
+
+    /**
+     * 领域对象集合转为数据传输对象集合
+     *
+     * @param navDoList 领域对象集合
+     * @return 数据传输对象集合  key-基金ID  value-数据传输对象集合
+     */
+    private Map<String, List<NavDto>> navDoListToNavDtoMap(List<NavDo> navDoList) {
+        Map<String, List<NavDto>> fundIdNavDtoListMap = new HashMap<>();
+
+        if (navDoList == null) {
+            return fundIdNavDtoListMap;
+        }
+
+        for (NavDo navDo : navDoList) {
+            NavDto navDto = new NavDto();
+            navDto.setFundId(navDo.getFundId());
+            if (navDo.getPriceDate() == null) {
+                continue;
+            }
+            navDto.setPriceDate(DateUtil.DateToString(navDo.getPriceDate(), DateConst.YYYY_MM_DD));
+            navDto.setOriginalNav(navDo.getNav());
+            navDto.setCumulativeNav(navDo.getCumulativeNav());
+            navDto.setCumulativeNavWithdrawal(navDo.getCumulativeNavWithdrawal());
+            if (navDo.getUpdatetime() != null) {
+                navDto.setUpdatetime(DateUtil.DateToString(navDo.getUpdatetime(), DateConst.YYYY_MM_DD_HH_MM_SS));
+            }
+            if (navDo.getCreatetime() != null) {
+                navDto.setCreatetime(DateUtil.DateToString(navDo.getCreatetime(), DateConst.YYYY_MM_DD));
+            }
+
+            if (fundIdNavDtoListMap.containsKey(navDo.getFundId())) {
+                List<NavDto> navDtoList = fundIdNavDtoListMap.get(navDo.getFundId());
+                navDtoList.add(navDto);
+            } else {
+                List<NavDto> navDtoList = new ArrayList<>();
+                navDtoList.add(navDto);
+                fundIdNavDtoListMap.put(navDo.getFundId(), navDtoList);
+            }
+        }
+        return fundIdNavDtoListMap;
+    }
+
+    /**
+     * 获取基金净值更新时间 大于 传入的开始时间的基金id
+     *
+     * @param startTime 开始时间
+     * @return 基金id列表
+     */
+    public List<NavDo> selectFundIdByStartTime(Date startTime) {
+        return navDoMapper.selectFundIdByStartTime(startTime);
+    }
+
+}

+ 77 - 0
src/main/java/com/smppw/analysis/domain/dao/PubliclyOfferedFundNavDao.java

@@ -0,0 +1,77 @@
+package com.smppw.analysis.domain.dao;
+
+import com.smppw.analysis.domain.pojo.PublicNavDo;
+import com.smppw.analysis.infrastructure.persistence.PublicNavDoMapper;
+import com.smppw.common.pojo.dto.NavDto;
+import com.smppw.common.pojo.enums.NavType;
+import com.smppw.constants.DateConst;
+import com.smppw.constants.NavConst;
+import com.smppw.utils.DateUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Repository
+public class PubliclyOfferedFundNavDao {
+
+    @Autowired
+    private PublicNavDoMapper publicNavDoMapper;
+
+    public static Map<String, List<NavDto>> convertToMap(List<PublicNavDo> navDoList) {
+        Map<String, List<NavDto>> fundIdNavDtoListMap = new HashMap<>();
+
+        if (navDoList == null) {
+            return fundIdNavDtoListMap;
+        }
+
+        for (PublicNavDo navDo : navDoList) {
+            NavDto navDto = new NavDto();
+            navDto.setFundId(navDo.getFundId());
+            if (navDo.getPriceDate() == null) {
+                continue;
+            }
+            navDto.setPriceDate(DateUtil.DateToString(navDo.getPriceDate(), DateConst.YYYY_MM_DD));
+            navDto.setOriginalNav(navDo.getNav());
+            navDto.setCumulativeNav(navDo.getCumulativeNav());
+            navDto.setCumulativeNavWithdrawal(navDo.getCumulativeNavWithdrawal());
+            if (navDo.getUpdatetime() != null) {
+                navDto.setUpdatetime(DateUtil.DateToString(navDo.getUpdatetime(), DateConst.YYYY_MM_DD_HH_MM_SS));
+            }
+            if (navDo.getCreatetime() != null) {
+                navDto.setCreatetime(DateUtil.DateToString(navDo.getCreatetime(), DateConst.YYYY_MM_DD));
+            }
+
+            if (fundIdNavDtoListMap.containsKey(navDo.getFundId())) {
+                List<NavDto> navDtoList = fundIdNavDtoListMap.get(navDo.getFundId());
+                navDtoList.add(navDto);
+            } else {
+                List<NavDto> navDtoList = new ArrayList<>();
+                navDtoList.add(navDto);
+                fundIdNavDtoListMap.put(navDo.getFundId(), navDtoList);
+            }
+        }
+        return fundIdNavDtoListMap;
+    }
+
+    public Map<String, List<NavDto>> getNav(List<String> fundIdList, String startDate, String endDate, NavType navType, boolean needUpdateAndCreateTime) {
+        String navFieldSql = "";
+        List<PublicNavDo> navDoList = null;
+        if (NavType.CumulativeNav == navType) {
+            navFieldSql = NavConst.CUMULATIVE_NAV_SQL_FIELD;
+        } else if (NavType.OriginalNav == navType) {
+            navFieldSql = NavConst.NAV_SQL_FIELD;
+        } else if (NavType.WithdrawalNav == navType) {
+            navFieldSql = NavConst.CUMULATIVE_NAV_WITHDRAWAL_SQL_FIELD;
+        } else if (NavType.All == navType) {
+            navFieldSql = NavConst.CUMULATIVE_NAV_SQL_FIELD + "," + NavConst.NAV_SQL_FIELD + "," + NavConst.CUMULATIVE_NAV_WITHDRAWAL_SQL_FIELD;
+        }
+        navDoList = publicNavDoMapper.listNavByTimeInterval(fundIdList, startDate, endDate, navFieldSql, needUpdateAndCreateTime);
+        Map<String, List<NavDto>> fundIdNavDtoListMap = convertToMap(navDoList);
+        return fundIdNavDtoListMap;
+    }
+
+}

+ 67 - 0
src/main/java/com/smppw/analysis/domain/dao/RiskOfFreeNavDao.java

@@ -0,0 +1,67 @@
+package com.smppw.analysis.domain.dao;
+
+import com.smppw.analysis.domain.pojo.DepositNavDo;
+import com.smppw.analysis.infrastructure.persistence.DepositNavDoMapper;
+import com.smppw.common.pojo.dto.NavDto;
+import com.smppw.constants.DateConst;
+import com.smppw.utils.DateUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Repository
+public class RiskOfFreeNavDao {
+    @Autowired
+    private DepositNavDoMapper depositNavMasterMapper;
+
+    public Map<String, List<NavDto>> getNav(List<String> indexIdList, String startDate, String endDate, boolean needUpdateAndCreateTime) {
+        List<DepositNavDo> navDoList = depositNavMasterMapper.listNavByTimeInterval(indexIdList, startDate, endDate, needUpdateAndCreateTime);
+        return navDoListToNavDtoMap(navDoList);
+    }
+
+    /**
+     * 领域对象集合转为数据传输对象集合
+     *
+     * @param navDoList 领域对象集合
+     * @return 数据传输对象集合  key-基金ID  value-数据传输对象集合
+     */
+    private Map<String, List<NavDto>> navDoListToNavDtoMap(List<DepositNavDo> navDoList) {
+        Map<String, List<NavDto>> fundIdNavDtoListMap = new HashMap<>();
+
+        if (navDoList == null) {
+            return fundIdNavDtoListMap;
+        }
+
+        for (DepositNavDo navDo : navDoList) {
+            NavDto navDto = new NavDto();
+            navDto.setFundId(navDo.getFundId());
+            if (navDo.getPriceDate() == null) {
+                continue;
+            }
+            navDto.setPriceDate(DateUtil.DateToString(navDo.getPriceDate(), DateConst.YYYY_MM_DD));
+            navDto.setOriginalNav(navDo.getNav());
+            navDto.setCumulativeNav(navDo.getNav());
+            navDto.setCumulativeNavWithdrawal(navDo.getNav());
+            if (navDo.getUpdatetime() != null) {
+                navDto.setUpdatetime(DateUtil.DateToString(navDo.getUpdatetime(), DateConst.YYYY_MM_DD));
+            }
+            if (navDo.getCreatetime() != null) {
+                navDto.setCreatetime(DateUtil.DateToString(navDo.getCreatetime(), DateConst.YYYY_MM_DD));
+            }
+
+            if (fundIdNavDtoListMap.containsKey(navDo.getFundId())) {
+                List<NavDto> navDtoList = fundIdNavDtoListMap.get(navDo.getFundId());
+                navDtoList.add(navDto);
+            } else {
+                List<NavDto> navDtoList = new ArrayList<>();
+                navDtoList.add(navDto);
+                fundIdNavDtoListMap.put(navDo.getFundId(), navDtoList);
+            }
+        }
+        return fundIdNavDtoListMap;
+    }
+}

+ 69 - 0
src/main/java/com/smppw/analysis/domain/dao/RongzhiIndexNavDao.java

@@ -0,0 +1,69 @@
+package com.smppw.analysis.domain.dao;
+
+import com.smppw.analysis.domain.pojo.IndexesRzIndexDo;
+import com.smppw.analysis.infrastructure.persistence.IndexesRzIndexDoMapper;
+import com.smppw.common.pojo.dto.NavDto;
+import com.smppw.constants.DateConst;
+import com.smppw.utils.DateUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Repository
+public class RongzhiIndexNavDao {
+
+    @Autowired
+    private IndexesRzIndexDoMapper indexesRzIndexDoMapper;
+
+    public Map<String, List<NavDto>> getNav(List<String> indexIdList, String startDate, String endDate, boolean needUpdateAndCreateTime) {
+        List<IndexesRzIndexDo> navDoList = indexesRzIndexDoMapper.listNavByTimeInterval(indexIdList, startDate, endDate, needUpdateAndCreateTime);
+        return navDoListToNavDtoMap(navDoList);
+    }
+
+    /**
+     * 领域对象集合转为数据传输对象集合
+     *
+     * @param navDoList 领域对象集合
+     * @return 数据传输对象集合  key-基金ID  value-数据传输对象集合
+     */
+    private Map<String, List<NavDto>> navDoListToNavDtoMap(List<IndexesRzIndexDo> navDoList) {
+        Map<String, List<NavDto>> fundIdNavDtoListMap = new HashMap<>();
+
+        if (navDoList == null) {
+            return fundIdNavDtoListMap;
+        }
+
+        for (IndexesRzIndexDo navDo : navDoList) {
+            NavDto navDto = new NavDto();
+            navDto.setFundId(navDo.getIndexId());
+            if (navDo.getEndDate() == null) {
+                continue;
+            }
+            navDto.setPriceDate(DateUtil.DateToString(navDo.getEndDate(), DateConst.YYYY_MM_DD));
+            navDto.setOriginalNav(navDo.getIndexValue());
+            navDto.setCumulativeNav(navDo.getIndexValue());
+            navDto.setCumulativeNavWithdrawal(navDo.getIndexValue());
+            if (navDo.getUpdatetime() != null) {
+                navDto.setUpdatetime(DateUtil.DateToString(navDo.getUpdatetime(), DateConst.YYYY_MM_DD_HH_MM_SS));
+            }
+            if (navDo.getCreatetime() != null) {
+                navDto.setCreatetime(DateUtil.DateToString(navDo.getCreatetime(), DateConst.YYYY_MM_DD));
+            }
+
+            if (fundIdNavDtoListMap.containsKey(navDo.getIndexId())) {
+                List<NavDto> navDtoList = fundIdNavDtoListMap.get(navDo.getIndexId());
+                navDtoList.add(navDto);
+            } else {
+                List<NavDto> navDtoList = new ArrayList<>();
+                navDtoList.add(navDto);
+                fundIdNavDtoListMap.put(navDo.getIndexId(), navDtoList);
+            }
+        }
+        return fundIdNavDtoListMap;
+    }
+
+}

+ 54 - 0
src/main/java/com/smppw/analysis/domain/pojo/DepositNavDo.java

@@ -0,0 +1,54 @@
+package com.smppw.analysis.domain.pojo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+public class DepositNavDo {
+    /**
+    * id
+    */
+    private Integer id;
+
+    /**
+    * 基金id,'HF'开头(后加36进制编码格式,不足8位长度左补零) 例:HF00000001
+    */
+    private String fundId;
+
+    /**
+    * 净值日期
+    */
+    private Date priceDate;
+
+    /**
+    * 单位净值
+    */
+    private BigDecimal nav;
+
+    /**
+    * 创建者Id,默认第一次创建者名称,创建后不变更
+    */
+    private Integer creatorid;
+
+    /**
+    * 创建时间,默认第一次创建的getdate()时间
+    */
+    private Date createtime;
+
+    /**
+    * 修改者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+    */
+    private Integer updaterid;
+
+    /**
+    * 修改时间;第一次创建时与CreatTime值相同,修改时与修改时间相同
+    */
+    private Date updatetime;
+
+    /**
+    * 记录的有效性;1-有效;0-无效;
+    */
+    private Integer isvalid;
+}

+ 112 - 0
src/main/java/com/smppw/analysis/domain/pojo/IndexesRzIndexDo.java

@@ -0,0 +1,112 @@
+package com.smppw.analysis.domain.pojo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+    * 分类周指标信息表
+    */
+@Data
+public class IndexesRzIndexDo {
+    /**
+    * ID自增,没意义
+    */
+    private Integer id;
+
+    /**
+    * 指数ID与index_profile的index_id关联
+    */
+    private String indexId;
+
+    /**
+    * 指数代码来源于indexes_profile
+    */
+    private String indexCode;
+
+    /**
+    * 指数截止月份
+    */
+    private Date endDate;
+
+    /**
+    * 本周属于的年份
+    */
+    private Integer yearofweek;
+
+    /**
+    * 一年中的第N周
+    */
+    private Integer weeks;
+
+    /**
+    * 策略,来源于d_strategy
+    */
+    private Integer strategy;
+
+    /**
+    * 子策略id
+    */
+    private Integer substrategy;
+
+    /**
+    * 三级策略
+    */
+    private Integer thirdStrategy;
+
+    /**
+    * 上一期指数值
+    */
+    private BigDecimal lastIndexValue;
+
+    /**
+    * 本期指数
+    */
+    private BigDecimal indexValue;
+
+    /**
+    * 指数周收益
+    */
+    private BigDecimal ret1w;
+
+    /**
+    * 纳入指数计算基金数量
+    */
+    private Integer inclCalFundCount;
+
+    /**
+    * 基金总数量
+    */
+    private Integer totalFundCount;
+
+    /**
+    * 是否是主策略周指数,0表示是主策略周指数,1表示是子策略周指数
+    */
+    private Integer isstrategy;
+
+    /**
+    * 创建者Id,默认第一次创建者名称,创建后不变更
+    */
+    private Integer creatorid;
+
+    /**
+    * 创建时间,默认第一次创建的getdate()时间
+    */
+    private Date createtime;
+
+    /**
+    * 修改者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+    */
+    private Integer updaterid;
+
+    /**
+    * 修改时间;第一次创建时与CreatTime值相同,修改时与修改时间相同
+    */
+    private Date updatetime;
+
+    /**
+    * 记录的有效性;1-有效;0-无效;
+    */
+    private Integer isvalid;
+}

+ 119 - 0
src/main/java/com/smppw/analysis/domain/pojo/MarketIndexesDo.java

@@ -0,0 +1,119 @@
+package com.smppw.analysis.domain.pojo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+    * 主要指数表
+    */
+@Data
+public class MarketIndexesDo {
+    private Integer id;
+
+    /**
+    * 指数类别id
+    */
+    private String indexId;
+
+    /**
+    * 指数代码
+    */
+    private String indexCode;
+
+    /**
+    * 日期
+    */
+    private Date priceDate;
+
+    /**
+    * 前收盘价
+    */
+    private BigDecimal preclose;
+
+    /**
+    * 开盘价
+    */
+    private BigDecimal open;
+
+    /**
+    * 最高价
+    */
+    private BigDecimal high;
+
+    /**
+    * 最低价
+    */
+    private BigDecimal low;
+
+    /**
+    * 收盘价
+    */
+    private BigDecimal close;
+
+    /**
+    * 成交量(万股)
+    */
+    private BigDecimal tradeVolumen;
+
+    /**
+    * 成交金额(万元)
+    */
+    private BigDecimal tradeAmount;
+
+    /**
+    * 涨跌
+    */
+    private BigDecimal waveRange;
+
+    /**
+    * 涨跌幅(%)
+    */
+    private BigDecimal dayPriceLimit;
+
+    /**
+    * 久期
+    */
+    private BigDecimal duration;
+
+    /**
+    * 凸性
+    */
+    private BigDecimal convexity;
+
+    /**
+    * 到期收益率(%)
+    */
+    private BigDecimal retFinal;
+
+    /**
+    * 平均票面利率(%)
+    */
+    private BigDecimal avgCouponRate;
+
+    /**
+    * 创建者Id,默认第一次创建者名称,创建后不变更
+    */
+    private Integer creatorid;
+
+    /**
+    * 创建时间,默认第一次创建的getdate()时间
+    */
+    private Date createtime;
+
+    /**
+    * 修改者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+    */
+    private Integer updaterid;
+
+    /**
+    * 修改时间;第一次创建时与CreatTime值相同,修改时与修改时间相同
+    */
+    private Date updatetime;
+
+    /**
+    * 记录的有效性;1-有效;0-无效;
+    */
+    private Byte isvalid;
+}

+ 74 - 0
src/main/java/com/smppw/analysis/domain/pojo/NavDo.java

@@ -0,0 +1,74 @@
+package com.smppw.analysis.domain.pojo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+public class NavDo {
+    /**
+    * id
+    */
+    private Integer id;
+
+    /**
+    * 基金id,'HF'开头(后加36进制编码格式,不足8位长度左补零) 例:HF00000001
+    */
+    private String fundId;
+
+    /**
+    * 净值日期
+    */
+    private Date priceDate;
+
+    /**
+    * 单位净值
+    */
+    private BigDecimal nav;
+
+    /**
+    * 考虑分红再投资的单位累计净值
+    */
+    private BigDecimal cumulativeNav;
+
+    /**
+    * 分红不投资的单位累计净值
+    */
+    private BigDecimal cumulativeNavWithdrawal;
+
+    /**
+    * 净值创新高或新低标志;1-创历史新高;2-创历史新低;3-既没有创历史新高也没有创历史新低;-1-其他
+    */
+    private Integer ishighOrLow;
+
+    /**
+    * 距离历史新高的距离,(历史最高累计净值-最新累计净值)*100%/最新累计净值
+    */
+    private BigDecimal tohighNavRatio;
+
+    /**
+    * 创建者Id,默认第一次创建者名称,创建后不变更
+    */
+    private Integer creatorid;
+
+    /**
+    * 创建时间,默认第一次创建的getdate()时间
+    */
+    private Date createtime;
+
+    /**
+    * 修改者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+    */
+    private Integer updaterid;
+
+    /**
+    * 修改时间;第一次创建时与CreatTime值相同,修改时与修改时间相同
+    */
+    private Date updatetime;
+
+    /**
+    * 记录的有效性;1-有效;0-无效;
+    */
+    private Integer isvalid;
+}

+ 77 - 0
src/main/java/com/smppw/analysis/domain/pojo/PublicNavDo.java

@@ -0,0 +1,77 @@
+package com.smppw.analysis.domain.pojo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+    * 公募净值表
+    */
+@Data
+public class PublicNavDo {
+    /**
+    * id
+    */
+    private Integer id;
+
+    /**
+    * 基金id,'HF'开头(后加36进制编码格式,不足8位长度左补零) 例:HF00000001
+    */
+    private String fundId;
+
+    /**
+    * 净值日期
+    */
+    private Date priceDate;
+
+    /**
+    * 单位净值
+    */
+    private BigDecimal nav;
+
+    /**
+    * 考虑分红再投资的单位累计净值
+    */
+    private BigDecimal cumulativeNav;
+
+    /**
+    * 分红不投资的单位累计净值
+    */
+    private BigDecimal cumulativeNavWithdrawal;
+
+    /**
+    * 净值创新高或新低标志;1-创历史新高;2-创历史新低;3-既没有创历史新高也没有创历史新低;-1-其他
+    */
+    private Integer ishighOrLow;
+
+    /**
+    * 距离历史新高的距离,(历史最高累计净值-最新累计净值)*100%/最新累计净值
+    */
+    private BigDecimal tohighNavRatio;
+
+    /**
+    * 创建者Id,默认第一次创建者名称,创建后不变更
+    */
+    private Integer creatorid;
+
+    /**
+    * 创建时间,默认第一次创建的getdate()时间
+    */
+    private Date createtime;
+
+    /**
+    * 修改者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+    */
+    private Integer updaterid;
+
+    /**
+    * 修改时间;第一次创建时与CreatTime值相同,修改时与修改时间相同
+    */
+    private Date updatetime;
+
+    /**
+    * 记录的有效性;1-有效;0-无效;
+    */
+    private Integer isvalid;
+}

+ 20 - 0
src/main/java/com/smppw/analysis/domain/service/BaseIndicatorServiceV2.java

@@ -0,0 +1,20 @@
+package com.smppw.analysis.domain.service;
+
+import com.smppw.common.pojo.IStrategy;
+import com.smppw.common.pojo.dto.calc.IndicatorCalcPropertyDto;
+import com.smppw.common.pojo.dto.indicator.CalcMultipleSecMultipleTimeRangeIndicatorReq;
+import com.smppw.common.pojo.dto.indicator.DateIntervalDto;
+import com.smppw.common.pojo.enums.*;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
+
+public interface BaseIndicatorServiceV2 {
+    Map<String, List<IndicatorCalcPropertyDto>> calcMultipleSecMultipleTimeRangeIndicator(CalcMultipleSecMultipleTimeRangeIndicatorReq req);
+
+    Map<String, List<IndicatorCalcPropertyDto>> getMultipleSecTrend(List<String> mainSecIdList, Map<String, String> secBenchmarkIdMap, List<String> indexIdList,
+                                                                    DateIntervalDto dateIntervalDto, Frequency frequency, BigDecimal fixedIncome, BigDecimal initValue, RaiseType raiseType,
+                                                                    IStrategy strategy, Visibility visibility, NavType navType, List<TrendType> trendTypeV2List, Boolean ifExtract, Integer userId);
+
+}

+ 27 - 0
src/main/java/com/smppw/analysis/domain/service/NavService.java

@@ -0,0 +1,27 @@
+package com.smppw.analysis.domain.service;
+
+import com.smppw.common.pojo.dto.DateValue;
+import com.smppw.common.pojo.enums.Frequency;
+import com.smppw.common.pojo.enums.NavType;
+import com.smppw.common.pojo.enums.Visibility;
+
+import java.util.List;
+import java.util.Map;
+
+public interface NavService {
+    Map<String, List<DateValue>> getSecIdDateValueNavListMapFromRedisAndDB(List<String> mainSecIdList, List<String> benchmarkIdList, List<String> indexList, String startDate, String endDate
+            , NavType navType, Visibility visibility, Integer curveTypeId, Integer strategyId, Map<String, Frequency> secFrequencyMap, boolean getRedisData);
+
+    Map<String, List<DateValue>> getSecIdDateValueNavListMapByDb(List<String> allSecIdList, String startDate, String endDate
+            , Integer curveTypeId, Integer strategyId, Visibility visibility, NavType navType, Map<String, Frequency> secFrequencyMap
+            , Map<String, Boolean> secIfExtractMap);
+
+    Map<String, List<DateValue>> getRongzhiIndexNavMap(List<String> rongzhiIndexIdList, String startDate, String endDate, NavType navType);
+
+    Map<String, List<DateValue>> getMarketIndexNavMap(List<String> marketIndexIdList, String startDate, String endDate, NavType navType);
+
+    Map<String, List<DateValue>> getPubliclyOfferedFundNavMap(List<String> fundIdList, String startDate, String endDate, NavType navType, Visibility visibility);
+
+    Map<String, List<DateValue>> getPrivatelyOfferedFundNavMap(List<String> fundIdList, String startDate, String endDate, NavType navType, Visibility visibility
+            , Map<String, Boolean> secIfExtractMap);
+}

+ 10 - 0
src/main/java/com/smppw/analysis/domain/service/SecTypeService.java

@@ -0,0 +1,10 @@
+package com.smppw.analysis.domain.service;
+
+import java.util.List;
+import java.util.Map;
+
+public interface SecTypeService {
+    String getFundType(String fundId);
+
+    Map<String, List<String>> getSecIdTypeMap(List<String> secIdList);
+}

+ 72 - 0
src/main/java/com/smppw/analysis/domain/service/impl/BaseIndicatorServiceV2Impl.java

@@ -0,0 +1,72 @@
+package com.smppw.analysis.domain.service.impl;
+
+import cn.hutool.core.util.StrUtil;
+import com.smppw.analysis.domain.service.BaseIndicatorServiceV2;
+import com.smppw.analysis.domain.service.NavService;
+import com.smppw.common.pojo.IStrategy;
+import com.smppw.common.pojo.dto.DateValue;
+import com.smppw.common.pojo.dto.calc.IndicatorCalcPropertyDto;
+import com.smppw.common.pojo.dto.indicator.CalcMultipleSecMultipleTimeRangeIndicatorReq;
+import com.smppw.common.pojo.dto.indicator.DateIntervalDto;
+import com.smppw.common.pojo.enums.*;
+import com.smppw.core.IndicatorService;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class BaseIndicatorServiceV2Impl implements BaseIndicatorServiceV2 {
+    private final NavService navService;
+
+    public BaseIndicatorServiceV2Impl(NavService navService) {
+        this.navService = navService;
+    }
+
+    @Override
+    public Map<String, List<IndicatorCalcPropertyDto>> calcMultipleSecMultipleTimeRangeIndicator(CalcMultipleSecMultipleTimeRangeIndicatorReq req) {
+        List<String> mainSecIdList = req.getMainSecIdList();
+        Map<String, String> secBenchmarkIdMap = req.getSecBenchmarkIdMap();
+        List<String> indexIdList = req.getIndexIdList();
+        RaiseType raiseType = req.getRaiseType();
+        IStrategy strategy = req.getStrategy();
+        Visibility visibility = req.getVisibility();
+        NavType navType = req.getNavType();
+        String riskOfFreeId = req.getRiskOfFreeId();
+
+        List<String> benchmarkIdList = new ArrayList<>();
+        for (Map.Entry<String, String> secBenchmarkIdMapEntry : secBenchmarkIdMap.entrySet()) {
+            String benchmarkId = secBenchmarkIdMapEntry.getValue();
+            if (StrUtil.isNotEmpty(benchmarkId)) {
+                benchmarkIdList.add(benchmarkId);
+            }
+        }
+        CurveType curveType = CurveType.getCurveType(raiseType, strategy);
+        if (StrUtil.isNotEmpty(riskOfFreeId)) {
+            benchmarkIdList.add(riskOfFreeId);
+        }
+        Map<String, List<DateValue>> allNavMap = navService.getSecIdDateValueNavListMapFromRedisAndDB(mainSecIdList, benchmarkIdList, indexIdList,
+                null, null, navType, visibility, curveType.getId(), strategy.getStrategyId(), new HashMap<>(), false);
+
+        return IndicatorService.getInstance().calcMultipleSecMultipleTimeRangeIndicator(req, allNavMap);
+    }
+
+    @Override
+    public Map<String, List<IndicatorCalcPropertyDto>> getMultipleSecTrend(List<String> mainSecIdList, Map<String, String> secBenchmarkIdMap, List<String> indexIdList, DateIntervalDto dateIntervalDto, Frequency frequency, BigDecimal fixedIncome, BigDecimal initValue, RaiseType raiseType, IStrategy strategy, Visibility visibility, NavType navType, List<TrendType> trendTypeV2List, Boolean ifExtract, Integer userId) {
+        List<String> benchmarkIdList = new ArrayList<>();
+        for (Map.Entry<String, String> secBenchmarkIdMapEntry : secBenchmarkIdMap.entrySet()) {
+            String benchmarkId = secBenchmarkIdMapEntry.getValue();
+            if (StrUtil.isNotEmpty(benchmarkId)) {
+                benchmarkIdList.add(benchmarkId);
+            }
+        }
+        CurveType curveType = CurveType.getCurveType(raiseType, strategy);
+        Map<String, List<DateValue>> allNavMap = navService.getSecIdDateValueNavListMapFromRedisAndDB(mainSecIdList, benchmarkIdList, indexIdList,
+                null, null, navType, visibility, curveType.getId(), strategy.getStrategyId(), new HashMap<>(), false);
+
+        return IndicatorService.getInstance().getMultipleSecTrend(mainSecIdList, secBenchmarkIdMap, indexIdList, dateIntervalDto, frequency, fixedIncome, initValue, trendTypeV2List, allNavMap);
+    }
+}

+ 324 - 0
src/main/java/com/smppw/analysis/domain/service/impl/NavServiceImpl.java

@@ -0,0 +1,324 @@
+package com.smppw.analysis.domain.service.impl;
+
+import com.smppw.analysis.domain.dao.*;
+import com.smppw.analysis.domain.service.NavService;
+import com.smppw.analysis.domain.service.SecTypeService;
+import com.smppw.analysis.infrastructure.utils.DateValueUtil;
+import com.smppw.common.pojo.dto.DateValue;
+import com.smppw.common.pojo.dto.NavDto;
+import com.smppw.common.pojo.enums.Frequency;
+import com.smppw.common.pojo.enums.NavType;
+import com.smppw.common.pojo.enums.Visibility;
+import com.smppw.constants.SecType;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+
+@Service
+@Slf4j
+public class NavServiceImpl implements NavService {
+
+    private static final Integer REDIS_PIPE_QUERY_SIZE = 50;
+    //    @Autowired
+//    private JedisDataUtil jedisData;
+//
+//    @Autowired
+//    private RedissonClient redissonClient;
+//
+    @Autowired
+    private SecTypeService secTypeService;
+    //
+//    @Autowired
+//    private FundInformationDao fundInformationDao;
+//
+//    @Autowired
+//    private CmAdvisoryPoolCurveInfoDao cmAdvisoryPoolCurveInfoDao;
+//
+    @Autowired
+    private PrivatelyOfferedFundNavDao privatelyOfferedFundNavDao;
+    @Autowired
+    private PubliclyOfferedFundNavDao publiclyOfferedFundNavDao;
+//
+//    @Autowired
+//    private CombinationNavDao combinationNavDao;
+    //
+//    @Autowired
+//    private PrivateFundNavDao privateFundNavDao;
+//
+//    @Autowired
+//    private FactorNavDao factorNavDao;
+//
+    @Autowired
+    private MarketIndexNavDao marketIndexNavDao;
+//
+//    @Autowired
+//    private UdfIndexNavDao udfIndexNavDao;
+//
+//    @Autowired
+//    private CompanyNavDao companyNavDao;
+//
+//    @Autowired
+//    private ManagerNavDao managerNavDao;
+//
+//    @Autowired
+//    private CmAdvisoryPoolCurveWeeklyDao cmAdvisoryPoolCurveWeeklyDao;
+//
+//    @Autowired
+//    private ThirdIndexNavDao thirdIndexNavDao;
+    @Autowired
+    private RongzhiIndexNavDao rongzhiIndexNavDao;
+//
+//    @Autowired
+//    private CmFittedAccruedCurveDao cmFittedAccruedCurveDao;
+//
+//    @Autowired
+//    private CmCombinationFundAccruedNavDao cmCombinationFundAccruedNavDao;
+//
+//    @Autowired
+//    private CmAccruedNavDao cmAccruedNavDao;
+    @Autowired
+    private RiskOfFreeNavDao riskOfFreeNavDao;
+
+    /**
+     * @param dateValueList 从小到大的净值序列
+     * @param date          日期
+     * @return 小于等于 date 的 日期最大的 日期
+     */
+    public static Integer getMostLeftLess(List<DateValue> dateValueList, String date) {
+        if (dateValueList == null || dateValueList.size() == 0) {
+            return -1;
+        }
+        int L = 0;
+        int R = dateValueList.size() - 1;
+        int ans = -1;
+        while (L <= R) {
+            int mid = (L + R) / 2;
+            if (dateValueList.get(mid) != null && dateValueList.get(mid).getDate().compareTo(date) <= 0) {
+                ans = mid;
+                L = mid + 1;
+            } else {
+                R = mid - 1;
+            }
+        }
+        return ans;
+    }
+
+    /**
+     * @param dateValueList 从小到大的净值序列
+     * @param date          日期
+     * @return 大于等于 date 的 日期最小的 日期
+     */
+    public static Integer getMostRightThan(List<DateValue> dateValueList, String date) {
+        if (dateValueList == null || Objects.requireNonNull(dateValueList).size() == 0) {
+            return -1;
+        } else if (dateValueList.get(dateValueList.size() - 1).getDate().compareTo(date) < 0) {
+            return dateValueList.size() - 1;
+        }
+        int low = 0;
+        int high = dateValueList.size() - 1;
+        while (low < high) {
+            //防止溢出
+            int mid = low + (high - low) / 2;
+            if (dateValueList.get(mid).getDate().compareTo(date) < 0) {
+                low = mid + 1;
+            } else {
+                high = mid;
+            }
+        }
+        return low;
+    }
+
+    @Override
+    public Map<String, List<DateValue>> getSecIdDateValueNavListMapFromRedisAndDB(List<String> mainSecIdList, List<String> benchmarkIdList, List<String> indexList
+            , String startDate, String endDate, NavType navType, Visibility visibility, Integer curveTypeId, Integer strategyId, Map<String, Frequency> secFrequencyMap, boolean getRedisData) {
+
+        //全部的标的集合
+        Map<String, Boolean> secIfExtractMap = new HashMap<>();
+        List<String> secIds = new ArrayList<>();
+        secIds.addAll(mainSecIdList);
+        secIds.addAll(benchmarkIdList);
+        secIds.addAll(indexList);
+//        if (extractNavServiceReq != null && extractNavServiceReq.isIfExtract()) {
+//            for (String mainSecId : mainSecIdList) {
+//                secIfExtractMap.put(mainSecId, true);
+//            }
+//        }
+
+        List<String> dbSecIds = new ArrayList<>();
+        Map<String, String> secKeyMap = new HashMap<>();
+
+        Map<String, List<DateValue>> allSecNavListMap = new HashMap<>();
+
+        //取DB
+        Map<String, List<DateValue>> secNavListMapDbData = getSecIdDateValueNavListMapByDb(dbSecIds, startDate, endDate, curveTypeId, strategyId, visibility, navType, secFrequencyMap, secIfExtractMap);
+        allSecNavListMap.putAll(secNavListMapDbData);
+
+        //将取DB的标的的净值存进redis
+//        cacheNavDataToRedis(dbSecIds, secKeyMap, curveTypeId, strategyId, visibility, navType, secFrequencyMap);
+
+        return allSecNavListMap;
+    }
+
+    @Override
+    public Map<String, List<DateValue>> getSecIdDateValueNavListMapByDb(List<String> allSecIdList, String startDate, String endDate
+            , Integer curveTypeId, Integer strategyId, Visibility visibility, NavType navType, Map<String, Frequency> secFrequencyMap
+            , Map<String, Boolean> secIfExtractMap) {
+
+        Map<String, List<DateValue>> allNavMap = new HashMap<>();
+
+        //对secId进行分类
+        Map<String, List<String>> secIdTypeMap = secTypeService.getSecIdTypeMap(allSecIdList);
+
+        //1.市场私募净值
+        List<String> marketPrivateFundIdList = secIdTypeMap.get(SecType.PRIVATELY_OFFERED_FUND);
+        if (marketPrivateFundIdList != null && marketPrivateFundIdList.size() > 0) {
+            Map<String, List<DateValue>> privatelyOfferedFundNavMap = getPrivatelyOfferedFundNavMap(marketPrivateFundIdList, startDate, endDate, navType, visibility, secIfExtractMap);
+            allNavMap.putAll(privatelyOfferedFundNavMap);
+        }
+
+        //2.市场公募净值
+        List<String> marketPublicFundIdList = secIdTypeMap.get(SecType.PUBLICLY_OFFERED_FUNDS);
+        if (marketPublicFundIdList != null && marketPublicFundIdList.size() > 0) {
+            Map<String, List<DateValue>> marketPubliclyOfferedFundNavMap = getPubliclyOfferedFundNavMap(marketPublicFundIdList, startDate, endDate, navType, visibility);
+            allNavMap.putAll(marketPubliclyOfferedFundNavMap);
+        }
+
+        //5.市场指数行情
+        List<String> marketIndexIdList = secIdTypeMap.get(SecType.INDEX_FUND);
+        if (marketIndexIdList != null && marketIndexIdList.size() > 0) {
+            Map<String, List<DateValue>> marketIndexNavMap = getMarketIndexNavMap(marketIndexIdList, startDate, endDate, navType);
+            allNavMap.putAll(marketIndexNavMap);
+        }
+
+        //7.融智指数行情
+        List<String> rongzhiIndexIdList = secIdTypeMap.get(SecType.RONGZHI_INDEX);
+        if (rongzhiIndexIdList != null && rongzhiIndexIdList.size() > 0) {
+            Map<String, List<DateValue>> rongzhiIndexIdNavMap = getRongzhiIndexNavMap(rongzhiIndexIdList, startDate, endDate, navType);
+            allNavMap.putAll(rongzhiIndexIdNavMap);
+        }
+
+        //13.无风险收益
+        List<String> riskOfFree = secIdTypeMap.get(SecType.RISK_OF_FREE);
+        if (riskOfFree != null && riskOfFree.size() > 0) {
+            Map<String, List<DateValue>> riskOfFreeNavMap = getRiskOfFreeNavMap(riskOfFree, startDate, endDate, navType);
+            allNavMap.putAll(riskOfFreeNavMap);
+        }
+
+        return allNavMap;
+    }
+
+    private Map<String, List<DateValue>> getRiskOfFreeNavMap(List<String> riskOfFree, String startDate, String endDate, NavType navType) {
+        Map<String, List<NavDto>> riskOfFreeNavMap = riskOfFreeNavDao.getNav(riskOfFree, startDate, endDate, false);
+        return SecNavDtoListMapToSecDateValueListMap(navType, riskOfFreeNavMap);
+    }
+
+    @Override
+    public Map<String, List<DateValue>> getRongzhiIndexNavMap(List<String> rongzhiIndexIdList, String startDate, String endDate, NavType navType) {
+        Map<String, List<NavDto>> rongzhiIndexIdNavDtoListMap = rongzhiIndexNavDao.getNav(rongzhiIndexIdList, startDate, endDate, false);
+        return SecNavDtoListMapToSecDateValueListMap(navType, rongzhiIndexIdNavDtoListMap);
+    }
+
+    @Override
+    public Map<String, List<DateValue>> getMarketIndexNavMap(List<String> marketIndexIdList, String startDate, String endDate, NavType navType) {
+        Map<String, List<NavDto>> indexIdNavDtoListMap = marketIndexNavDao.getNav(marketIndexIdList, startDate, endDate, false);
+        return SecNavDtoListMapToSecDateValueListMap(navType, indexIdNavDtoListMap);
+    }
+
+    @Override
+    public Map<String, List<DateValue>> getPubliclyOfferedFundNavMap(List<String> fundIdList, String startDate, String endDate, NavType navType, Visibility visibility) {
+        Map<String, List<NavDto>> fundIdNavDtoListMap = publiclyOfferedFundNavDao.getNav(fundIdList, startDate, endDate, navType, false);
+        return SecNavDtoListMapToSecDateValueListMap(navType, fundIdNavDtoListMap);
+    }
+
+    @Override
+    public Map<String, List<DateValue>> getPrivatelyOfferedFundNavMap(List<String> fundIdList, String startDate, String endDate, NavType navType, Visibility visibility
+            , Map<String, Boolean> secIfExtractMap) {
+
+        //不取费后净值的ID
+        List<String> notAccfilterFundIdList = new ArrayList<>();
+        //取费后净值的ID
+        List<String> accfilterFundIdList = new ArrayList<>();
+        Map<String, List<NavDto>> allFundIdNavDtoListMap = new HashMap<>();
+
+//        for (String fundId : fundIdList) {
+//            Boolean secIfExtract = secIfExtractMap.get(fundId);
+//            if (secIfExtract != null && secIfExtract) {
+//                accfilterFundIdList.add(fundId);
+//            } else {
+//                notAccfilterFundIdList.add(fundId);
+//            }
+//        }
+
+        //取非费后净值
+        if (notAccfilterFundIdList.size() > 0) {
+            Map<String, List<NavDto>> fundIdNavDtoListMap = privatelyOfferedFundNavDao.getNav(notAccfilterFundIdList, startDate, endDate, navType, false);
+            allFundIdNavDtoListMap.putAll(fundIdNavDtoListMap);
+        }
+
+        return SecNavDtoListMapToSecDateValueListMap(navType, allFundIdNavDtoListMap);
+    }
+
+    private Map<String, List<DateValue>> SecNavDtoListMapToSecDateValueListMap(NavType navType, Map<String, List<NavDto>> secIdNavDtoListMap) {
+        Map<String, List<DateValue>> secIdDateValueListMap = new HashMap<>();
+        for (Map.Entry<String, List<NavDto>> fundIdNavDtoListEntry : secIdNavDtoListMap.entrySet()) {
+            List<NavDto> navDtoList = fundIdNavDtoListEntry.getValue();
+            String fundId = fundIdNavDtoListEntry.getKey();
+            List<DateValue> dateValueList = DateValueUtil.convertNavList(navDtoList, navType);
+            secIdDateValueListMap.put(fundId, dateValueList);
+        }
+        return secIdDateValueListMap;
+    }
+
+//    private void cacheNavDataToRedis(List<String> dbSecIds, Map<String, String> secKeyMap, Integer curveType, Integer strategy, Visibility visibility, NavType navType, Map<String, Frequency> secFrequencyMap) {
+//
+////        if (extractNavServiceReq != null && extractNavServiceReq.isIfExtract()) {
+////            return;
+////        }
+//
+//        List<String> needCacheSecIdList = new ArrayList<>();
+//        for (String dbSecId : dbSecIds) {
+//            String key = secKeyMap.get(dbSecId);
+//            if (StringUtil.isNotEmpty(key)) {
+//                needCacheSecIdList.add(dbSecId);
+//            }
+//        }
+//
+//        if (dbSecIds.size() != 0) {
+//            taskExecutor.execute(()-> {
+//                // 确保取出全量数据DB数据
+//                Map<String, List<DateValue>> secNavListMapDbData = getSecIdDateValueNavListMapByDb(needCacheSecIdList, null, null, curveType, strategy, visibility, navType, secFrequencyMap, extractNavServiceReq, new HashMap<>());
+//                for (String needCacheSecId : needCacheSecIdList) {
+//
+//                    String secType = secTypeService.getFundType(needCacheSecId);
+//
+//                    String redisKey = secKeyMap.get(needCacheSecId);
+//                    List<DateValue> dateValueList = secNavListMapDbData.get(needCacheSecId);
+//                    Map<String, Double> dateNavMap = new HashMap<>();
+//                    for (DateValue dateValue : dateValueList) {
+//                        dateNavMap.put(dateValue.getDate(), dateValue.getValue());
+//                    }
+//
+//                    RLock lock = redissonClient.getLock(RedisUtils.getHashLockKey(needCacheSecId, redisKey));
+//                    try{
+//                        if (lock.tryLock(1,10, TimeUnit.SECONDS)) {
+//                            String dateNavMapJsonString = JSON.toJSONString(dateNavMap);
+//                            RMap<String, String> secMap = redissonClient.getMap(needCacheSecId);
+//                            secMap.put(redisKey, dateNavMapJsonString);
+//                            if (SecType.PRIVATE_FUND.equals(secType)) {
+//                                secMap.expire(15,TimeUnit.SECONDS);
+//                            }
+//                        } else {
+//                            log.error("redis write nav error, get lock failed.key: {}", redisKey);
+//                        }
+//                    }catch(Exception e){
+//                        log.error("redis write nav error: {}", e.getMessage(), e);
+//                    }finally{
+//                        lock.unlock();
+//                    }
+//                }
+//            });
+//        }
+//    }
+}

+ 105 - 0
src/main/java/com/smppw/analysis/domain/service/impl/SecTypeServiceImpl.java

@@ -0,0 +1,105 @@
+package com.smppw.analysis.domain.service.impl;
+
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.StrUtil;
+import com.smppw.analysis.infrastructure.persistence.IndexesRzIndexDoMapper;
+import com.smppw.analysis.domain.service.SecTypeService;
+import com.smppw.common.cache.CaffeineLocalCache;
+import com.smppw.common.pojo.enums.strategy.Strategy;
+import com.smppw.constants.SecType;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Rain
+ * @date 2023/3/16 10:03
+ * @description
+ */
+@Service
+public class SecTypeServiceImpl implements SecTypeService {
+    public static final String HF = "HF";
+    public static final String MF = "MF";
+    public static final String CF = "CF";
+    public static final String FA = "FA";
+    public static final String CI = "CI";
+    public static final String CO = "CO";
+    public static final String PL = "PL";
+    public static final String PO = "PO";
+    public static final String IN = "IN";
+    public static final String AP = "AP";
+    private static final Map<String, Integer> INDEX_EXIST = MapUtil.newConcurrentHashMap();
+    @Autowired
+    private IndexesRzIndexDoMapper indexesRzIndexDoMapper;
+
+    @Override
+    public String getFundType(String fundId) {
+        if (fundId == null) {
+            return null;
+        }
+        if (fundId.startsWith(HF)) {
+            return SecType.PRIVATELY_OFFERED_FUND;
+        } else if (fundId.startsWith(MF)) {
+            return SecType.PUBLICLY_OFFERED_FUNDS;
+        } else if (fundId.startsWith(CF)) {
+            return SecType.PRIVATE_FUND;
+        } else if (fundId.startsWith(FA)) {
+            return SecType.FACTOR;
+        } else if (fundId.startsWith(CI)) {
+            return SecType.UDF_INDEX;
+        } else if (fundId.startsWith(CO)) {
+            return SecType.COMPANY;
+        } else if (fundId.startsWith(PL)) {
+            return SecType.MANAGER;
+        } else if (fundId.startsWith(PO)) {
+            return SecType.COMBINATION;
+        } else if (StrUtil.isNumeric(fundId)) {
+            if (Strategy.isStrategy(fundId)) {
+                return SecType.STRATEGY;
+            }
+        } else if (fundId.startsWith(IN)) {
+            List<String> thirdIndexes = CaffeineLocalCache.getThirdIndexes();
+            if (thirdIndexes.contains(fundId)) {
+                return SecType.THIRD_INDEX_FUND;
+            }
+            List<String> riskOfFreeIdList = CaffeineLocalCache.getRiskOfFreeId();
+            if (riskOfFreeIdList.contains(fundId)) {
+                return SecType.RISK_OF_FREE;
+            }
+            Integer isExist = INDEX_EXIST.get(fundId);
+            if (isExist == null) {
+                isExist = indexesRzIndexDoMapper.isExist(fundId);
+                INDEX_EXIST.put(fundId, isExist);
+            }
+            if (isExist.compareTo(0) == 0) {
+                return SecType.INDEX_FUND;
+            } else {
+                return SecType.RONGZHI_INDEX;
+            }
+        } else if (fundId.startsWith(AP)) {
+            return SecType.ADVISORY_POOL_CURVE;
+        }
+        return null;
+    }
+
+    @Override
+    public Map<String, List<String>> getSecIdTypeMap(List<String> secIdList) {
+        Map<String, List<String>> secIdTypeMap = new HashMap<>(10);
+        for (String secId : secIdList) {
+            String secIdType = getFundType(secId);
+            if (secIdTypeMap.containsKey(secIdType)) {
+                List<String> list = secIdTypeMap.get(secIdType);
+                list.add(secId);
+            } else {
+                List<String> list = new ArrayList<>();
+                list.add(secId);
+                secIdTypeMap.put(secIdType, list);
+            }
+        }
+        return secIdTypeMap;
+    }
+}

+ 15 - 0
src/main/java/com/smppw/analysis/infrastructure/persistence/DepositNavDoMapper.java

@@ -0,0 +1,15 @@
+package com.smppw.analysis.infrastructure.persistence;
+
+import com.smppw.analysis.domain.pojo.DepositNavDo;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface DepositNavDoMapper {
+    List<String> listRiskOfFreeId();
+
+    List<DepositNavDo> listNavByTimeInterval(@Param("indexIdList") List<String> indexIdList, @Param("startDate") String startDate, @Param("endDate") String endDate,
+                                             @Param("needUpdateAndCreateTime") boolean needUpdateAndCreateTime);
+}

+ 16 - 0
src/main/java/com/smppw/analysis/infrastructure/persistence/IndexesRzIndexDoMapper.java

@@ -0,0 +1,16 @@
+package com.smppw.analysis.infrastructure.persistence;
+
+import com.smppw.analysis.domain.pojo.IndexesRzIndexDo;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface IndexesRzIndexDoMapper {
+
+    List<IndexesRzIndexDo> listNavByTimeInterval(@Param("indexIdList") List<String> indexIdList, @Param("startDate") String startDate, @Param("endDate") String endDate,
+                                                 @Param("needUpdateAndCreateTime") boolean needUpdateAndCreateTime);
+
+    Integer isExist(@Param("indexId") String indexId);
+}

+ 32 - 0
src/main/java/com/smppw/analysis/infrastructure/persistence/MarketIndexesDoMapper.java

@@ -0,0 +1,32 @@
+package com.smppw.analysis.infrastructure.persistence;
+
+import com.smppw.analysis.domain.pojo.MarketIndexesDo;
+import com.smppw.common.pojo.dto.NavDto;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface MarketIndexesDoMapper {
+
+    List<MarketIndexesDo> listNavByTimeInterval(@Param("indexIdList") List<String> indexIdList, @Param("startDate") String startDate, @Param("endDate") String endDate,
+                                                @Param("needUpdateAndCreateTime") boolean needUpdateAndCreateTime);
+
+    /**
+     * 根据指数ID获取指数最新的收盘价日期
+     *
+     * @param indexIds
+     * @return
+     */
+    List<NavDto> getLatestInfoByIndexId(@Param("indexIds") List<String> indexIds);
+
+    /**
+     * 获取指数id指定日期的收盘价
+     *
+     * @param indexId       指数id
+     * @param priceDateList 指定日期列表
+     * @return 指定日期的收盘价
+     */
+    List<MarketIndexesDo> selectIndexNavByPriceDate(@Param("indexId") String indexId, @Param("priceDateList") List<String> priceDateList);
+}

+ 24 - 0
src/main/java/com/smppw/analysis/infrastructure/persistence/NavDoMapper.java

@@ -0,0 +1,24 @@
+package com.smppw.analysis.infrastructure.persistence;
+
+import com.smppw.analysis.domain.pojo.NavDo;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.Date;
+import java.util.List;
+
+@Repository
+public interface NavDoMapper {
+
+    List<NavDo> listNavByTimeInterval(@Param("fundIdList") List<String> fundIdList, @Param("startDate") String startDate, @Param("endDate") String endDate,
+                                      @Param("navFieldSql") String navFieldSql, @Param("needUpdateAndCreateTime") boolean needUpdateAndCreateTime);
+
+    /**
+     * 获取基金净值更新时间 大于 传入的开始时间的基金id
+     *
+     * @param startTime 开始时间
+     * @return 基金id列表
+     */
+    List<NavDo> selectFundIdByStartTime(@Param("startTime") Date startTime);
+
+}

+ 13 - 0
src/main/java/com/smppw/analysis/infrastructure/persistence/PublicNavDoMapper.java

@@ -0,0 +1,13 @@
+package com.smppw.analysis.infrastructure.persistence;
+
+import com.smppw.analysis.domain.pojo.PublicNavDo;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface PublicNavDoMapper {
+    List<PublicNavDo> listNavByTimeInterval(@Param("fundIdList") List<String> fundIdList, @Param("startDate") String startDate, @Param("endDate") String endDate,
+                                            @Param("navFieldSql") String navFieldSql, @Param("needUpdateAndCreateTime") boolean needUpdateAndCreateTime);
+}

+ 48 - 0
src/main/java/com/smppw/analysis/infrastructure/utils/DateValueUtil.java

@@ -0,0 +1,48 @@
+package com.smppw.analysis.infrastructure.utils;
+
+import com.smppw.common.pojo.dto.DateValue;
+import com.smppw.common.pojo.dto.NavDto;
+import com.smppw.common.pojo.enums.NavType;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class DateValueUtil {
+
+    public static List<DateValue> convertNavList(List<NavDto> navDtoList, NavType navType) {
+        List<DateValue> dateValueList = new ArrayList<>();
+        for (NavDto navDto : navDtoList) {
+            DateValue dateValue = new DateValue();
+            dateValue.setDate(navDto.getPriceDate());
+            if (NavType.WithdrawalNav == navType) {
+                dateValue.setValue(navDto.getCumulativeNavWithdrawal() != null ? navDto.getCumulativeNavWithdrawal().doubleValue() : null);
+            } else if (NavType.OriginalNav == navType) {
+                dateValue.setValue(navDto.getOriginalNav() != null ? navDto.getOriginalNav().doubleValue() : null);
+            } else if (NavType.All == navType) {
+                dateValue.setValue(navDto.getOriginalNav() != null ? navDto.getOriginalNav().doubleValue() : null);
+                dateValue.setOriginalNav(navDto.getOriginalNav() != null ? navDto.getOriginalNav() : null);
+                dateValue.setCumulativeNav(navDto.getCumulativeNav() != null ? navDto.getCumulativeNav() : null);
+                dateValue.setCumulativeNavWithdrawal(navDto.getCumulativeNavWithdrawal() != null ? navDto.getCumulativeNavWithdrawal() : null);
+            } else {
+                dateValue.setValue(navDto.getCumulativeNav() != null ? navDto.getCumulativeNav().doubleValue() : null);
+            }
+            dateValueList.add(dateValue);
+        }
+        return dateValueList;
+    }
+    public static List<Map<String, Object>> convertDecimalMapToList(Map<String, BigDecimal> originalMap) {
+        List<Map<String, Object>> resultList = new ArrayList<>();
+        for (Map.Entry<String, BigDecimal> entry : originalMap.entrySet()) {
+            String date = entry.getKey();
+            Map<String, Object> convertedMap = new HashMap<>();
+            convertedMap.put("date", date);
+            convertedMap.put("value", entry.getValue());
+            resultList.add(convertedMap);
+        }
+        return resultList;
+    }
+
+}

+ 26 - 0
src/main/java/com/smppw/analysis/interfaces/FundApi.java

@@ -0,0 +1,26 @@
+package com.smppw.analysis.interfaces;
+
+import cn.hutool.core.collection.ListUtil;
+import com.smppw.analysis.application.dto.RateRiskIndicatorParams;
+import com.smppw.analysis.application.service.PerformanceService;
+import com.smppw.common.pojo.enums.Indicator;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+@RestController
+@RequestMapping("/v1/api/fund")
+public class FundApi {
+    private final PerformanceService performanceService;
+
+    public FundApi(PerformanceService performanceService) {
+        this.performanceService = performanceService;
+    }
+
+    @GetMapping("/indicators")
+    public Map<String, Object> indicator(RateRiskIndicatorParams params) {
+        return this.performanceService.rateRiskIndicators(params, ListUtil.toList(Indicator.INDICATOR_TYPE_ARRAY), ListUtil.toList(Indicator.RISK_TABLE_EXCESS_INDICATOR_ARRAY));
+    }
+}

+ 54 - 0
src/main/resources/application.yaml

@@ -0,0 +1,54 @@
+server:
+  port: 8899
+  undertow:
+    accesslog:
+      dir: .logs
+      enabled: true
+      pattern: common
+      prefix: access_log
+      suffix: log
+    threads:
+      # io线程数,主要执行费阻塞的任务
+      io: 8
+      # 阻塞任务线程池
+      worker: 50
+    # 每块buffer的空间大小,越小的空间被利用越充分
+    buffer-size: 1024
+    # 是否分配的直接内存
+    direct-buffers: true
+
+spring:
+  application:
+    name: smppw-analysis
+  datasource:
+    url: jdbc:mysql://47.112.140.222:3306/rz_hfdb_core?allowMultiQueries=true&useSSL=false&rewriteBatchedStatements=true&zeroDateTimeBehavior=convertToNull
+    username: rz_cm_master
+    password: TbLuENLK
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    hikari:
+      pool-name: hfdb_core
+      # 连接池最大连接数,默认是10
+      maximum-pool-size: 10
+      # 此属性控制从池返回的连接的默认自动提交行为,默认值:true
+      auto-commit: true
+      # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟
+      max-lifetime: 900000
+      # 数据库连接超时时间,设置为300秒超时
+      connection-timeout: 300000
+      # keepalive time
+      keepalive-time: 60000
+  data:
+    redis:
+      host: 192.168.1.28
+      port: 6379
+      password: twznW28grxzk
+      timeout: 30000
+      database: 2
+      jedis:
+        pool:
+          max-idle: 6    #最大空闲数
+          max-active: 10 #最大连接数
+          min-idle: 2    #最小空闲数
+
+mybatis:
+  mapper-locations: classpath:mapping/**/*.xml

+ 42 - 0
src/main/resources/mapping/DepositNavDoMapper.xml

@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.smppw.analysis.infrastructure.persistence.DepositNavDoMapper">
+  <resultMap id="BaseResultMap" type="com.smppw.analysis.domain.pojo.DepositNavDo">
+    <!--@mbg.generated-->
+    <!--@Table deposit_nav-->
+    <id column="id" property="id" />
+    <result column="fund_id" property="fundId" />
+    <result column="price_date" property="priceDate" />
+    <result column="nav" property="nav" />
+    <result column="creatorid" property="creatorid" />
+    <result column="createtime" property="createtime" />
+    <result column="updaterid" property="updaterid" />
+    <result column="updatetime" property="updatetime" />
+    <result column="isvalid" property="isvalid" />
+  </resultMap>
+  <sql id="Base_Column_List">
+    <!--@mbg.generated-->
+    id, fund_id, price_date, nav, creatorid, createtime, updaterid, updatetime, isvalid
+  </sql>
+  <select id="listRiskOfFreeId" resultType="java.lang.String">
+    select distinct fund_id from deposit_nav where isvalid = 1
+  </select>
+
+  <select id="listNavByTimeInterval" resultMap="BaseResultMap">
+    select fund_id, price_date, nav
+    <if test="needUpdateAndCreateTime">
+      , updatetime, createtime
+    </if>
+    from deposit_nav where isvalid = 1
+    <if test="startDate != null and startDate != ''">
+      AND price_date &gt;= #{startDate}
+    </if>
+    <if test="endDate != null and endDate != ''">
+      AND price_date &lt;= #{endDate}
+    </if>
+    AND fund_id in
+    <foreach collection="indexIdList" item="indexId" index="index" open="(" separator="," close=")">
+      #{indexId}
+    </foreach>
+  </select>
+</mapper>

+ 57 - 0
src/main/resources/mapping/IndexesRzIndexDoMapper.xml

@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.smppw.analysis.infrastructure.persistence.IndexesRzIndexDoMapper">
+  <resultMap id="BaseResultMap" type="com.smppw.analysis.domain.pojo.IndexesRzIndexDo">
+    <!--@mbg.generated-->
+    <!--@Table indexes_rz_index-->
+    <id column="id" property="id" />
+    <result column="index_id" property="indexId" />
+    <result column="index_code" property="indexCode" />
+    <result column="end_date" property="endDate" />
+    <result column="yearofweek" property="yearofweek" />
+    <result column="weeks" property="weeks" />
+    <result column="strategy" property="strategy" />
+    <result column="substrategy" property="substrategy" />
+    <result column="third_strategy" property="thirdStrategy" />
+    <result column="last_index_value" property="lastIndexValue" />
+    <result column="index_value" property="indexValue" />
+    <result column="ret_1w" property="ret1w" />
+    <result column="incl_cal_fund_count" property="inclCalFundCount" />
+    <result column="total_fund_count" property="totalFundCount" />
+    <result column="isstrategy" property="isstrategy" />
+    <result column="creatorid" property="creatorid" />
+    <result column="createtime" property="createtime" />
+    <result column="updaterid" property="updaterid" />
+    <result column="updatetime" property="updatetime" />
+    <result column="isvalid" property="isvalid" />
+  </resultMap>
+  <sql id="Base_Column_List">
+    <!--@mbg.generated-->
+    id, index_id, index_code, end_date, yearofweek, weeks, strategy, substrategy, third_strategy, 
+    last_index_value, index_value, ret_1w, incl_cal_fund_count, total_fund_count, isstrategy, 
+    creatorid, createtime, updaterid, updatetime, isvalid
+  </sql>
+
+  <select id="listNavByTimeInterval" resultMap="BaseResultMap">
+    select index_id, end_date, index_value
+    <if test="needUpdateAndCreateTime">
+      , updatetime, createtime
+    </if>
+    from indexes_rz_index where isvalid = 1
+    <if test="startDate != null and startDate != ''">
+      AND end_date &gt;= #{startDate}
+    </if>
+    <if test="endDate != null and endDate != ''">
+      AND end_date &lt;= #{endDate}
+    </if>
+    AND index_id in
+    <foreach collection="indexIdList" item="indexId" index="index" open="(" separator="," close=")">
+      #{indexId}
+    </foreach>
+  </select>
+
+  <select id="isExist" resultType="java.lang.Integer">
+    select count(id) from indexes_rz_index where index_id = #{indexId} and isvalid = 1
+  </select>
+
+</mapper>

+ 95 - 0
src/main/resources/mapping/MarketIndexesDoMapper.xml

@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.smppw.analysis.infrastructure.persistence.MarketIndexesDoMapper">
+  <resultMap id="BaseResultMap" type="com.smppw.analysis.domain.pojo.MarketIndexesDo">
+    <!--@mbg.generated-->
+    <!--@Table market_indexes-->
+    <id column="id" property="id" />
+    <result column="index_id" property="indexId" />
+    <result column="index_code" property="indexCode" />
+    <result column="price_date" property="priceDate" />
+    <result column="preclose" property="preclose" />
+    <result column="open" property="open" />
+    <result column="high" property="high" />
+    <result column="low" property="low" />
+    <result column="close" property="close" />
+    <result column="trade_volumen" property="tradeVolumen" />
+    <result column="trade_amount" property="tradeAmount" />
+    <result column="wave_range" property="waveRange" />
+    <result column="day_price_limit" property="dayPriceLimit" />
+    <result column="duration" property="duration" />
+    <result column="convexity" property="convexity" />
+    <result column="ret_final" property="retFinal" />
+    <result column="avg_coupon_rate" property="avgCouponRate" />
+    <result column="creatorid" property="creatorid" />
+    <result column="createtime" property="createtime" />
+    <result column="updaterid" property="updaterid" />
+    <result column="updatetime" property="updatetime" />
+    <result column="isvalid" property="isvalid" />
+  </resultMap>
+  <sql id="Base_Column_List">
+    <!--@mbg.generated-->
+    id, index_id, index_code, price_date, preclose, `open`, high, low, `close`, trade_volumen, 
+    trade_amount, wave_range, day_price_limit, duration, convexity, ret_final, avg_coupon_rate, 
+    creatorid, createtime, updaterid, updatetime, isvalid
+  </sql>
+
+  <select id="listNavByTimeInterval" resultMap="BaseResultMap">
+    select index_id, price_date, `close`
+    <if test="needUpdateAndCreateTime">
+      , updatetime, createtime
+    </if>
+    from market_indexes where isvalid = 1
+    <if test="startDate != null and startDate != ''">
+      AND price_date &gt;= #{startDate}
+    </if>
+    <if test="endDate != null and endDate != ''">
+      AND price_date &lt;= #{endDate}
+    </if>
+    AND index_id in
+    <foreach collection="indexIdList" item="indexId" index="index" open="(" separator="," close=")">
+      #{indexId}
+    </foreach>
+  </select>
+
+  <resultMap id="NavDto" type="com.smppw.common.pojo.dto.NavDto">
+    <result property="fundId" column="index_id"/>
+    <result property="priceDate" column="price_date"/>
+    <result property="nav" column="close"/>
+  </resultMap>
+
+  <select id="getLatestInfoByIndexId" resultMap="NavDto">
+    SELECT
+    t.index_id,
+    t.price_date,
+    m.close
+    FROM
+    market_indexes m
+    INNER JOIN (
+    SELECT
+    index_id,
+    max( price_date ) AS price_date
+    FROM
+    market_indexes
+    WHERE
+    index_id
+    IN
+    <foreach collection="indexIds" index="index" item="indexId" open="(" close=")" separator=",">
+      #{indexId}
+    </foreach>
+    GROUP BY index_id
+    ) AS t ON t.index_id = m.index_id
+    AND t.price_date = m.price_date
+  </select>
+
+  <select id="selectIndexNavByPriceDate" resultType="com.smppw.analysis.domain.pojo.MarketIndexesDo">
+    select index_id as indexId, close as close, price_date as priceDate
+    from market_indexes
+    where index_id = #{indexId} and isvalid=1
+    and price_date in
+    <foreach collection="priceDateList" index="index" item="priceDate" open="(" separator="," close=")">
+      #{priceDate}
+    </foreach>
+  </select>
+
+</mapper>

+ 52 - 0
src/main/resources/mapping/NavDoMapper.xml

@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.smppw.analysis.infrastructure.persistence.NavDoMapper">
+  <resultMap id="BaseResultMap" type="com.smppw.analysis.domain.pojo.NavDo">
+    <!--@mbg.generated-->
+    <!--@Table nav-->
+    <id column="id" property="id" />
+    <result column="fund_id" property="fundId" />
+    <result column="price_date" property="priceDate" />
+    <result column="nav" property="nav" />
+    <result column="cumulative_nav" property="cumulativeNav" />
+    <result column="cumulative_nav_withdrawal" property="cumulativeNavWithdrawal" />
+    <result column="ishigh_or_low" property="ishighOrLow" />
+    <result column="tohigh_nav_ratio" property="tohighNavRatio" />
+    <result column="creatorid" property="creatorid" />
+    <result column="createtime" property="createtime" />
+    <result column="updaterid" property="updaterid" />
+    <result column="updatetime" property="updatetime" />
+    <result column="isvalid" property="isvalid" />
+  </resultMap>
+  <sql id="Base_Column_List">
+    <!--@mbg.generated-->
+    id, fund_id, price_date, nav, cumulative_nav, cumulative_nav_withdrawal, ishigh_or_low, 
+    tohigh_nav_ratio, creatorid, createtime, updaterid, updatetime, isvalid
+  </sql>
+
+  <select id="listNavByTimeInterval" resultMap="BaseResultMap">
+    select fund_id, price_date, ${navFieldSql}
+    <if test="needUpdateAndCreateTime">
+      , updatetime, createtime
+    </if>
+    from nav where isvalid = 1
+    <if test="startDate != null and startDate != ''">
+      AND price_date &gt;= #{startDate}
+    </if>
+    <if test="endDate != null and endDate != ''">
+      AND price_date &lt;= #{endDate}
+    </if>
+    AND fund_id in
+    <foreach collection="fundIdList" item="fundId" index="index" open="(" separator="," close=")">
+      #{fundId}
+    </foreach>
+  </select>
+
+  <select id="selectFundIdByStartTime" resultType="com.smppw.analysis.domain.pojo.NavDo">
+    select fund_id as fundId, updatetime as updatetime
+    from nav
+    where isvalid = 1
+      AND updatetime &gt; #{startTime}
+  </select>
+
+</mapper>

+ 44 - 0
src/main/resources/mapping/PublicNavDoMapper.xml

@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.smppw.analysis.infrastructure.persistence.PublicNavDoMapper">
+  <resultMap id="BaseResultMap" type="com.smppw.analysis.domain.pojo.PublicNavDo">
+    <!--@mbg.generated-->
+    <!--@Table public_nav-->
+    <id column="id" property="id" />
+    <result column="fund_id" property="fundId" />
+    <result column="price_date" property="priceDate" />
+    <result column="nav" property="nav" />
+    <result column="cumulative_nav" property="cumulativeNav" />
+    <result column="cumulative_nav_withdrawal" property="cumulativeNavWithdrawal" />
+    <result column="ishigh_or_low" property="ishighOrLow" />
+    <result column="tohigh_nav_ratio" property="tohighNavRatio" />
+    <result column="creatorid" property="creatorid" />
+    <result column="createtime" property="createtime" />
+    <result column="updaterid" property="updaterid" />
+    <result column="updatetime" property="updatetime" />
+    <result column="isvalid" property="isvalid" />
+  </resultMap>
+  <sql id="Base_Column_List">
+    <!--@mbg.generated-->
+    id, fund_id, price_date, nav, cumulative_nav, cumulative_nav_withdrawal, ishigh_or_low, 
+    tohigh_nav_ratio, creatorid, createtime, updaterid, updatetime, isvalid
+  </sql>
+
+  <select id="listNavByTimeInterval" resultMap="BaseResultMap">
+    select fund_id, price_date, ${navFieldSql}
+    <if test="needUpdateAndCreateTime">
+      , updatetime, createtime
+    </if>
+    from public_nav where isvalid = 1
+    <if test="startDate != null and startDate != ''">
+      AND price_date &gt;= #{startDate}
+    </if>
+    <if test="endDate != null and endDate != ''">
+      AND price_date &lt;= #{endDate}
+    </if>
+    AND fund_id in
+    <foreach collection="fundIdList" item="fundId" index="index" open="(" separator="," close=")">
+      #{fundId}
+    </foreach>
+  </select>
+</mapper>

+ 13 - 0
src/test/java/com/smppw/analysis/DataAnalysisApplicationTests.java

@@ -0,0 +1,13 @@
+package com.smppw.analysis;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class DataAnalysisApplicationTests {
+
+    @Test
+    void contextLoads() {
+    }
+
+}